• open CV对图像的各类操作


    本文章用于记录自己使用open CV过程中的要点,便于遗忘时查看。

    首先使用

        using namespace std;
        using namespace cv;

    避免每次都需要敲 ::cv及::std;
    图像的读写显示存取

    图像定义:

    Mat image;


    图像读取:

    imread(const String & filename,int flags = IMREAD_COLOR);

        支持格式有:

        Windows bitmaps - *.bmp, *.dib (always supported)
        JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
        JPEG 2000 files - *.jp2 (see the Notes section)
        Portable Network Graphics - *.png (see the Notes section)
        WebP - *.webp (see the Notes section)
        Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
        Sun rasters - *.sr, *.ras (always supported)
        TIFF files - *.tiff, *.tif (see the Notes section)
        OpenEXR Image files - *.exr (see the Notes section)
        Radiance HDR - *.hdr, *.pic (always supported)
        Raster and Vector geospatial data supported by Gdal (see the Notes section)

        读取方式有:

        IMREAD_UNCHANGED                                        按照图片原格式读入.
        IMREAD_GRAYSCALE                                         将图片转为单通道灰色图.
        IMREAD_COLOR                                                 将图片转为BGR3通道 .
        IMREAD_ANYDEPTH                                           如果图片是16-bit/32-bit ,则保持不变,其他的都转为8-bit.
        IMREAD_ANYCOLOR                                          图像以任何可能的颜色格式读取.
        IMREAD_LOAD_GDAL                                        使用GDAL载入图像.
        IMREAD_REDUCED_GRAYSCALE_2                  将图片转为单通道灰色图,同时将图片尺寸裁剪到 1/2.
        IMREAD_REDUCED_COLOR_2                          将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/2.
        IMREAD_REDUCED_GRAYSCALE_4                  将图片转为单通道灰色图,同时将图片尺寸裁剪到  1/4.
        IMREAD_REDUCED_COLOR_4                          将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/4.
        IMREAD_REDUCED_GRAYSCALE_8                  将图片转为单通道灰色图,同时将图片尺寸裁剪到 1/8.
        IMREAD_REDUCED_COLOR_8                          将图片转为BGR 3通道,同时将图片尺寸裁剪到 1/8.
        IMREAD_IGNORE_ORIENTATION                        如果设置,不旋转图像根据EXIF的定位标志

    显示图像:

    imshow(const String & winname, InputArray mat);

    显示窗口:

    namedWindow(const String & winname,int flags = WINDOW_AUTOSIZE)  

        WINDOW_NORMAL设置了这个值,用户便可以改变窗口的大小
        WINDOW_AUTOSIZE如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小。
        WINDOW_OPENGL 如果设置了这个值的话,窗口创建的时候便会支持OpenGL。

    waitKey(int delay = 0)

    这个函数用来等待,读取和处理事件。当我们没有输入,只需要窗口停留,就可以将参数设为0。

    图像保存:

    imwrite(const String & filename InputArray img, const vector< int > & params = vector< int >())  

    图像缩放、旋转、截取、叠加

    缩放:

    resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )

    InputArray src     -原图像
    OutputArray dst    -输出图像
    Size dsize         -目标图像的大小
    double fx=0        -在x轴上的缩放比例
    double fy=0        -在y轴上的缩放比例
    int interpolation  -插值方式,有以下四种方式
        INTER_NN      -最近邻插值
        INTER_LINEAR  -双线性插值 (缺省使用)
        INTER_AREA    -使用象素关系重采样,当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 INTER_NN 方法。
        INTER_CUBIC   -立方插值。

    dsize与(fx,fy)不能同时为0

    旋转:

        Mat rotMat;Point rotCenter = Point(x,y);    //    x,y为旋转中心坐标
        rotMat = getRotationMatrix2D(Point2f center, double angle, double scale);//获取旋转矩阵,angle为逆时针;scale为缩放比例.
        warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar());

    根据getAffineTransform或getRotationMatrix2D得到的变换矩阵,计算变换后的图像。

    src为输入图像

    dst为变换后图像,类型与src一致。
    M为变换矩阵,需要通过其它函数获得,当然也可以手动输入。
    dsize为输出图像的大小

    flags,插值算法,详细如下:

        INTER_NEAREST        = 0,  //最近邻插值  
        INTER_LINEAR         = 1, //双线性插值  
        INTER_CUBIC          = 2, //双三次插值  
        INTER_AREA           = 3, //区域插值,使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。
        INTER_LANCZOS4       = 4, //Lanczos插值(超过8×8像素邻域的Lanczos插值)
        INTER_MAX            = 7,  
        WARP_FILL_OUTLIERS   = 8, //填充所有输出图像的象素  
        WARP_INVERSE_MAP     = 16  //逆变换

    borderMode为边界处理方式:

        BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i`  
        BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`  
        BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`  
        BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`  
        BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`  
        BORDER_TRANSPARENT = 5, //!< `uvwxyz|absdefgh|ijklmno`  
        BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101  
        BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101  

        BORDER_ISOLATED    = 16 //!< do not look outside of ROI  

    截取:

        Mat imageROI;
        imageROI = image(Rect(100, 100, 400, 400));

    或者用:

    imageROI = image(Range(100, 400),Range(100, 400));

    叠加:

    addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);

    公式为: dst = src1*alpha + src2*beta + gamma;

    注意:图像大小必须一致。如果不一致,可以用ROI方法:

    首先在原图中取出需要添加的位置图像:

    imageROI = image(Rect(200, 200, image_to_add.cols, image_to_add.rows));

    然后将需要添加的图像融合:

    addWeighted(image_to_add, 0.8, imageROI, 0.1, 0., imageROI);

    这样需要叠加的图像 image_to_add 就添加到imageROI区域了。
    直方图、梯度、滤波

    直方图:
            参考:点击打开链接

    sobel算子计算梯度:

            参考:点击打开链接

    直方图均衡:

        equalizeHist(InputArray src,
                     OutputArray dst
        );

    中值滤波:

        blur(InputArray src,
             OutputArray dst,
             Size ksize,
             Point anchor = Point(-1,-1),
             int borderType = BORDER_DEFAULT
        );

    高斯滤波:

        GaussianBlur(InputArray src,
                     OutputArray dst,
                     Size ksize,
                     double sigmaX,
                     double sigmaY = 0,
                     int borderType = BORDER_DEFAULT
        );

    双边滤波:

        bilateralFilter(InputArray src,
                        OutputArray dst,
                        int d,
                        double sigmaColor,
                        double sigmaSpace,
                        int borderType = BORDER_DEFAULT
        );

    方框滤波:

        boxFilter(InputArray src,
                  OutputArray dst,
                  int ddepth,
                  Size ksize,
                  Point anchor = Point(-1,-1),
                  bool normalize = true,
                  int borderType = BORDER_DEFAULT
        );


    颜色空间转换

    参考:点击打开链接

    边缘、轮廓

    用Sobel计算边缘

     假定输入图像矩阵为 I,卷积核大小为 3x3,则水平一阶导数 Gx 和垂直一阶导数 Gy 分别为:

      OpenCV 中,Sobel 函数如下:

        void cv::Sobel   (     
            InputArray  src,    // 输入图像
            OutputArray  dst,   // 输出图像
            int      ddepth,    // 输出图像深度,-1 表示等于 src.depth()
            int      dx,        // 水平方向的阶数
            int      dy,        // 垂直方向的阶数
            int     ksize = 3,    // 卷积核的大小,常取 1, 3, 5, 7 等奇数
            double  scale = 1,    // 缩放因子,应用于计算结果
            double  delta = 0,    // 增量数值,应用于计算结果
            int borderType = BORDER_DEFAULT // 边界模式
        );

    用Scharr卷积核计算:

    当卷积核大小为 3x3 时,使用 sobel 卷积核来计算并不是很精确,此时常用 Scharr 卷积核来代替,如下:

      而 Sharr 函数,本质上就是令 ksize = 3 且使用 Scharr 卷积核的 Sobel 函数。

        void cv::Scharr (     
            InputArray  src,    
            OutputArray  dst,    
            int      ddepth,    
            int      dx,        
            int      dy,        
            double  scale = 1,
            double  delta = 0,
            int     borderType = BORDER_DEFAULT        
        );

      对于 Scharr 函数,要求 dx 和 dy 都 >= 0 且 dx + dy == 1,假如 dx 和 dy 都设为 1,则会抛出异常。

      因此,对于 Sobel 和 Scharr 函数,通常各自求其 x 和 y 方向的导数,然后通过加权来进行边缘检测。

    用 Laplace算子计算:

        void cv::Laplacian (     
            InputArray     src,
            OutputArray    dst,
            int       ddepth,
            int       ksize = 1,
            double    scale = 1,
            double    delta = 0,
            int       borderType = BORDER_DEFAULT
        );

    用Canny算子计算:

    Canny 边缘检测算子,其算法步骤大体如下:

    1) 用高斯滤波器对输入图像做平滑处理 (大小为 5x5 的高斯核)

    2) 计算图像的梯度强度和角度方向 ( x 和 y 方向上的卷积核)

      角度方向近似为四个可能值,即 0, 45, 90, 135

    3) 对图像的梯度强度进行非极大抑制

       可看做边缘细化:只有候选边缘点被保留,其余的点被移除

    4) 利用双阈值检测和连接边缘

        若候选边缘点大于上阈值,则被保留;小于下阈值,则被舍弃;处于二者之间,须视其所连接的像素点,大于上阈值则被保留,反之舍弃

        void cv::Canny (     
            InputArray    image,    // 输入图像 (8位)
            OutputArray   edges,    // 输出图像 (单通道,8位)
            double      threshold1,  // 下阈值
            double      threshold2,  // 上阈值
            int         apertureSize = 3,
            bool        L2gradient = false
        );

    找出轮廓直线:

        HoughLines( InputArray image,
                    OutputArray lines,//line[i][0]为半径,line[i][1]为角度.定义用    vector<Vec2f> lines;
                    double rho,//半径
                    double theta,//角度
                    int threshold,
                    double srn = 0,
                    double stn = 0,
                    double min_theta = 0,
                    double max_theta = CV_PI
        );

    例子参考:
            Houghlines找出轮廓直线

    找出闭合轮廓:

        findContours(InputOutputArray image,
                    OutputArrayOfArrays contours,//    vector<vector<Point>> contours;
                    OutputArray hierarchy,//    vector<Vec4i> hierarchy
                    int mode,    //    CV_RETR_EXTERNAL只检测最外围轮廓
                                 //    CV_RETR_LIST   检测所有的轮廓,无等级
                                 //    CV_RETR_CCOMP  检测所有的轮廓,但所有轮廓只建立两个等级关系
                                 //    CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构
                    int method,    //    CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
                                   //    CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息
                                   //    CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS
                    Point offset = Point()
    ————————————————
    版权声明:本文为CSDN博主「benedict_tao」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/benedict_tao/article/details/79871150

  • 相关阅读:
    hdu 5007 水题 (2014西安网赛A题)
    hdu 1698 线段树(成段替换 区间求和)
    poj 3468 线段树 成段增减 区间求和
    hdu 2795 公告板 (单点最值)
    UVaLive 6833 Miscalculation (表达式计算)
    UVaLive 6832 Bit String Reordering (模拟)
    CodeForces 124C Prime Permutation (数论+贪心)
    SPOJ BALNUM (数位DP)
    CodeForces 628D Magic Numbers (数位DP)
    POJ 3252 Round Numbers (数位DP)
  • 原文地址:https://www.cnblogs.com/lykbk/p/13073634.html
Copyright © 2020-2023  润新知