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

上一篇:Vue3学习(十三)之 Modal 对话框、表单的使用


下一篇:算法训练 采油区域