OpenCV边缘检测:Sobel算子,Laplace算子,Canny算子,以及Hough变换检测直线

OpenCV边缘检测

原理:
参考链接:https://blog.csdn.net/poem_qianmo/article/details/25560901

Sobel算子

OpenCV调用:

C++: void Sobel (
InputArray src,//输入图
 OutputArray dst,//输出图
 int ddepth,//输出图像的深度
 int dx,
 int dy,
 int ksize=3,
 double scale=1,
 double delta=0,
 int borderType=BORDER_DEFAULT );
  • 第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。

  • 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。

  • 第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:

    • 若src.depth() = CV_8U, 取ddepth=-1/CV_16S/CV_32F/CV_64F
    • 若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
    • 若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
    • 若src.depth() = CV_64F, 取ddepth = -1/CV_64F
    • 第四个参数,int类型dx,x 方向上的差分阶数。
    • 第五个参数,int类型dy,y方向上的差分阶数。
    • 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
    • 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。

    我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。

  • 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。

  • 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。

自写Sobel算子边缘检测:


//把图像的各个像素点的值存到一个二维数组,增加代码的可读性
    int img_garry[imgHeight][imgWidth];
    for(int i = 0; i<imgHeight; i++)
    {
        for(int j = 0; j<imgWidth;j++)
        {
            img_garry[i][j] = grayData[i*imgWidth+j];
        }
        
    }



//sobel算法
    IplImage* sobel_img = NULL; //创建用于灰度图像的结构体指针
    sobel_img = cvCreateImage(cvSize(imgWidth,imgHeight), imgDepth, 1 );            //创建单通道的色彩空间用于灰度变换
    
    uchar *sobel_Data = (uchar*) sobel_img->imageData;//声明无符号char型指针指向结构体的变量imageData
    double Gmax = 150; //设定阈值Gmax
    double Gx=0;
    double Gy=0;
    double G =0;
    for(int i = 1;i<imgHeight-2; i++)
        for(int j = 1;j<imgWidth-2; j++)
        {
            Gx =  -1 * img_garry[i-1][j-1] + 0 * img_garry[i-1][ j ] + 1 * img_garry[i-1][j+1]
                + -2 * img_garry[ i ][j-1] + 0 * img_garry[ i ][ j ] + 2 * img_garry[ i ][j+1]
                + -1 * img_garry[i+1][j-1] + 0 * img_garry[i+1][ j ] + 1 * img_garry[i+1][j+1];
            
            Gy =  -1 * img_garry[i-1][j-1] + -2 * img_garry[i-1][ j ] + -1 * img_garry[i-1][j+1]
                +  0 * img_garry[ i ][j-1] +  0 * img_garry[ i ][ j ] +  0 * img_garry[ i ][j+1]
                +  1 * img_garry[i+1][j-1] +  2 * img_garry[i+1][ j ] +  1 * img_garry[i+1][j+1];
        
    
    G = sqrt(Gx*Gx+Gy*Gy);
    
  if(G>Gmax)
      sobel_Data[i*imgWidth+j]=255;
  else
      sobel_Data[i*imgWidth+j] = 0;

        }
    
cvShowImage("sobel_img", sobel_img);        //显示彩色图像灰度处理的图像

Laplace算子

OpenCV调用:

C++: void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT );
  • 第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
  • 第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和通道数。
  • 第三个参数,int类型的ddepth,目标图像的深度。
  • 第四个参数,int类型的ksize,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。
  • 第五个参数,double类型的scale,计算拉普拉斯值的时候可选的比例因子,有默认值1
  • 第六个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0
  • 第七个参数,
    int类型的borderType,边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate()处得到更详细的信息。

Laplacian()函数其实主要是利用sobel算子的运算。它通过加上sobel算子运算出的图像x方向和y方向上的导数,来得到我们载入图像的拉普拉斯变换结果。

自写Sobel算子边缘检测:

 //laplace算法
    IplImage* laplace_img = NULL; //创建用于灰度图像的结构体指针
    laplace_img = cvCreateImage(cvSize(imgWidth,imgHeight), imgDepth, 1 );            //创建单通道的色彩空间用于灰度变换
     
    uchar *laplace_Data = (uchar*) laplace_img->imageData;//声明无符号char型指针指向结构体的变量imageData
    
 
    double L =0;
    for(int i = 1;i<imgHeight-2; i++)
    {
          for(int j = 1;j<imgWidth-2; j++)
          {
              L =  0 * img_garry[i-1][j-1] +  1 * img_garry[i-1][ j ] +  0 * img_garry[i-1][j+1]
                +  1 * img_garry[ i ][j-1] + -4 * img_garry[ i ][ j ] +  1 * img_garry[ i ][j+1]
                +  0 * img_garry[i+1][j-1] +  1 * img_garry[i+1][ j ] +  0 * img_garry[i+1][j+1];
                                   
            if(L>255)
               laplace_Data[i*imgWidth+j] = 255;
            else if( 0<L & L<255)
              laplace_Data[i*imgWidth+j] = L ;
            else if(L<0)
              laplace_Data[i*imgWidth+j] = 0 ;
          }
        
    }

    
    cvShowImage("laplace_img", laplace_img);
    

Canny算子

OpenCV调用:

C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
  • 第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。

  • 第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。

  • 第三个参数,double类型的threshold1,第一个滞后性阈值。

  • 第四个参数,double类型的threshold2,第二个滞后性阈值。

  • 第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3

  • 第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false

  • 需要注意的是,这个函数阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间。

openCV调用示例:

  //Canny算法
    Mat Canny_Image = imread("/Users/inbc/Desktop/OpenCV学习/opencv_test_3/666.jpg");//注意修改路径
        if (!Canny_Image.data){
            cout << "falied to read" << endl;
            system("pause");
            //return;
        }
        Mat srcGray;
        cvtColor(Canny_Image, srcGray, CV_BGR2GRAY);
        //高斯滤波
        GaussianBlur(srcGray, srcGray, Size(3, 3),
            0, 0, BORDER_DEFAULT);
        //Canny检测
        int edgeThresh =100;
        Mat Canny_result;
        Canny(Canny_Image, Canny_result, edgeThresh, edgeThresh * 3, 3); //调用Canny算子
        imshow("Canny_Image", Canny_Image);
        imshow("Canny_Image", Canny_result);
    
 

Hough变换检测直线

OpenCV调用:

C++:void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
  • 第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
  • 第二个参数,InputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1,x_2, y_2) 表示,其中,(x_1, y_1)(x_2, y_2) 是是每个检测到的线段的结束点。
  • 第三个参数,double类型的rho, 以像素为单位的距离精度。 另一种形容方式是直线搜索时的进步尺寸的单位半径。
  • 第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
  • 第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。 大于阈值threshold 的线段才可以被检测通过并返回到结果中。
  • 第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
  • 第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

OpenCV调用示例:

 //Hough变换检测直线
        Mat Hough_Image = imread("/Users/inbc/Desktop/OpenCV学习/opencv_test_3/666.jpg", 0);//注意修改路径
        Mat CannyImg;
        Canny(Hough_Image, CannyImg, 70, 200, 3);
        imshow("CannyImg_2", CannyImg);
     
        Mat DstImg;
        cvtColor(Hough_Image, DstImg, CV_GRAY2BGR);
     
        vector<Vec4i> Lines;
         HoughLinesP(CannyImg, Lines, 1, CV_PI / 360, 170,30,15);
        for (size_t i = 0; i < Lines.size(); i++)
        {
            line(DstImg, Point(Lines[i][0], Lines[i][1]), Point(Lines[i][2], Lines[i][3]), Scalar(0, 0, 255), 2, 8);
        }
        imshow("Hough_Image", DstImg);
上一篇:翻译:《实用的Python编程》03_02_More_functions


下一篇:(五)OpenCV-Python学习—边缘检测1