我尝试在C++中实现Canny筛选器。我希望得到这样的结果
c++ - C++中的Canny过滤器-LMLPHP

但我得到了结果
c++ - C++中的Canny过滤器-LMLPHP

非最大抑制后的图像和输出图像看起来不连贯,不稳定

我的代码如下

#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。
  • 5x5可能对于该高斯内核来说太小(使用更大的高斯内核,例如11x11,您可以使用较低的阈值,并具有更好的信噪比)
  • 的滞后部分似乎也有问题。我没有详细检查您的代码,但是为了滞后,您需要实现一个在强边附近遵循弱边(> thres_low)的递归过程,在您的代码中看不到这种递归调用。
  • 关于c++ - C++中的Canny过滤器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31638159/

    10-10 13:34