OpenCV邊緣檢測:Sobel算子,Laplace算子,Canny算子,以及Hough變換檢測直線

原理:
參考鏈接: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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章