Canny在C ++中过滤

时间:2015-07-26 14:32:21

标签: c++ opencv

我尝试在C ++中实现canny过滤器。我希望得到这样的结果 enter image description here

但我得到了结果 enter image description here

非最大抑制和输出图像后的图像似乎脱节,而不是实心

我的代码如下

#include<stdio.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cmath>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <time.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

int main(){
    cv::Mat inImage = cv::imread("C:\\Users\\DUY\\Desktop\\lena.jpg");
    cv::Mat outImage;
    cv::Mat rgbaImage;
    cv::Mat greyImage;
    cv::Mat blurImage;
    cv::Mat edgeMag;
    cv::Mat edgeDir;
    cv::Mat suppress;
    cv::cvtColor(inImage, rgbaImage, CV_BGR2RGBA);
    int numRows = rgbaImage.rows;
    int numCols = rgbaImage.cols;


    cv::cvtColor(rgbaImage, greyImage, CV_RGBA2GRAY);
    blurImage.create(numRows, numCols, CV_8UC1);
    edgeMag.create(numRows, numCols, CV_8UC1);
    edgeDir.create(numRows, numCols, CV_8UC1);
    suppress.create(numRows, numCols, CV_8UC1);
    outImage.create(numRows, numCols, CV_8UC1);


    clock_t start, end;
    start = clock();
    //------------------- Gaussian filter-----------------------//
    cv::Mat gaussianMask = (cv::Mat_<int>(5,5) << 2, 4, 5, 4, 2, 4, 9, 12,   9, 4, 5, 12, 15, 12, 5, 
                                            4, 9, 12, 9, 4, 2, 4, 5, 4, 2);

    for(int index_x = 2; index_x < numCols - 2; index_x++){
        for(int index_y = 2; index_y < numRows - 2; index_y++){
            float value = 0;
            for(int i = -2; i <= 2 ; i++){
                for(int j = -2; j <= 2; j++){
                    value = value + greyImage.at<unsigned char>(index_x+j, index_y+i) * gaussianMask.at<int>(i+2,j+2) ;
                }
            }

             value = value/159;

             blurImage.at<unsigned char>(index_x, index_y) = (unsigned char) value;
        }
    }
    end = clock();
    //------------------ Find the intensity gradient of the image---------------------//
    cv::Mat GxMask = (cv::Mat_<int>(3,3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
    cv::Mat GyMask = (cv::Mat_<int>(3,3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);

    for(int index_x = 1;index_x<numCols -1;index_x++){
       for(int index_y=1;index_y<numRows -1; index_y++){

           float mag = 0;

           float Gx = 0, Gy = 0;
           for(int i=-1;i<=1;i++){
               for(int j=-1;j<=1;j++){

                    Gx = Gx + blurImage.at<unsigned char>(index_x+i, index_y+j) * GxMask.at<int>(i+1,j+1);
                    Gy = Gy + blurImage.at<unsigned char>(index_x+i, index_y+j) * GyMask.at<int>(i+1,j+1);
               }
           }

           mag = sqrt(Gx*Gx + Gy*Gy);
           edgeMag.at<unsigned char>(index_x, index_y) = mag;
           float thisAngle = (atan2(Gx, Gy)/3.14159)*180;
           float newAngle;
           if ( ( (thisAngle < 22.5) && (thisAngle > -22.5) ) || (thisAngle > 157.5) || (thisAngle < -157.5) )
                newAngle = 0;
           if ( ( (thisAngle > 22.5) && (thisAngle < 67.5) ) || ( (thisAngle < -112.5) && (thisAngle > -157.5) ) )
               newAngle = 45;
           if ( ( (thisAngle > 67.5) && (thisAngle < 112.5) ) || ( (thisAngle < -67.5) && (thisAngle > -112.5) ) )
               newAngle = 90;
           if ( ( (thisAngle > 112.5) && (thisAngle < 157.5) ) || ( (thisAngle < -22.5) && (thisAngle > -67.5) ) )
           newAngle = 135;
           edgeDir.at<unsigned char>(index_x, index_y) = newAngle;
       }
    }
    //--------------------------Non-maximum suppression------------------------//
    for(int i = 1;i<numCols -1;i++){
       for(int j=1;j<numRows -1; j++){
            if((edgeDir.at<unsigned char>(i,j) == 0 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j))||
            (edgeDir.at<unsigned char>(i,j) == 90 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i,j+1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i,j-1))||
            (edgeDir.at<unsigned char>(i,j) == 45 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j-1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j+1))||
            (edgeDir.at<unsigned char>(i,j) == 135 && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i+1,j+1) && edgeMag.at<unsigned char>(i,j) > edgeMag.at<unsigned char>(i-1,j-1))){
                    suppress.at<unsigned char>(i,j) = edgeMag.at<unsigned char>(i,j);   
            }
             else{
                suppress.at<unsigned char>(i,j) = 0;
            }
        }
    }
    //-------------------------Hysteresis---------------------------//
    for(int i = 1;i<numCols -1;i++){
        for(int j=1;j<numRows -1; j++){
            int upperThreshold = 60;
            int lowerThreshold = 30;
            if(suppress.at<unsigned char>(i,j) > upperThreshold){
                outImage.at<unsigned char>(i,j) = 255;
            }
            if(suppress.at<unsigned char>(i,j) < lowerThreshold){
                outImage.at<unsigned char>(i,j)  = 0;
            }
        }
    }

    for(int i = 1;i<numCols -1;i++){
        for(int j=1;j<numRows -1; j++){
            int upperThreshold = 60;
            int lowerThreshold = 30;
            if(suppress.at<unsigned char>(i,j) < upperThreshold && suppress.at<unsigned char>(i,j) > lowerThreshold){
                for(int m = -1; m <= 1; m++){
                    for(int n = -1; n <= 1; n++){
                        if(outImage.at<unsigned char>(i+n,j+m) == 255){
                            outImage.at<unsigned char>(i,j) = 255;
                            break;
                        }
                    }
                }
            }
        }
    }


    float time = ((float)(end-start))/CLOCKS_PER_SEC*1000;
    printf("function: %f ms\n", time);
    //-----------------show image-------------------//
    cv::imshow("raw", inImage);
    cv::imshow("suppress", suppress);
    cv::imshow("out",outImage);
    cv::waitKey();
}
你能解释一下吗?非常感谢你

1 个答案:

答案 0 :(得分:1)

  • 您的高斯内核应校准为总和1.
  • 5x5可能对于那个高斯内核而言太小(使用更高的高斯内核,例如11x11,你可以使用更低的阈值,具有更好的信噪比)
  • 在滞后部分似乎也存在问题。我没有详细检查你的代码,但是对于迟滞你需要在强边缘附近的弱边缘(&gt; thres_low)之后实现一个递归的程序,我在你的代码中看不到这样的递归调用。