2015-07-26 4 views
1

Я пытаюсь реализовать фильтр canny в C++. Я ожидаю, чтобы получить результаты, как этот enter image description hereCanny filter in C++

, но я получил результат 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(); 
} 

Не могли бы вы объяснить мне? Большое спасибо

+2

Если вы используете OpenCV, вы можете просто использовать фильтр Canny [в библиотеке] (http://docs.opencv.org/modules/imgproc/doc/feature_detection.html#canny). – vukung

+0

Почему вы не используете реализованный canny в opencv ?? –

+0

Я хочу реализовать в C++ для понимания алгоритма ^^, но результат не такой, как я ожидаю. Вы можете мне помочь? спасибо ^^ –

ответ

1
  • Ваш гс-ядро должно быть откалиброван, чтобы подвести до 1.
  • 5x5, вероятно, слишком мал для этого гаусс ядра (с большим гауссова ядра, например, 11х11, вы можете использовать более низкие tresholds , имеющий лучшее соотношение сигнал/шум)
  • также есть проблема в части гистерезиса. Я не проверял ваш код подробно, но для гистерезиса вам нужно реализовать рекурсивную процедуру, которая следует за слабыми краями (> thres_low) в окрестности сильного края, я не вижу такой рекурсивный вызов в вашем коде.