Canny using separate functions

asked 2016-12-26 03:48:17 -0500

dkurtaev gravatar image

updated 2016-12-27 00:21:08 -0500

Hi! I've tried to write Canny edge detector using OpenCV's functions for better understanding. As I can see, my own pipeline has wrong results after non-maximum suppression.

  cv::GaussianBlur(input, blur, cv::Size(5, 5), 1.4, 1.4);
  cv::Sobel(blur, dx, CV_32F, 1, 0, 3);
  cv::Sobel(blur, dy, CV_32F, 0, 1, 3);
  cv::cartToPolar(dx, dy, magnitudes, angles);

  cv::Mat edges = cv::Mat::zeros(img.size(), CV_8UC1);
  for (int y = 1; y < angles.rows - 1; ++y) {
    for (int x = 1; x < angles.cols - 1; ++x) {
      float a = angles.at<float>(y, x);
      float m = magnitudes.at<float>(y, x);
      if (a > CV_PI) {
        a -= CV_PI;
      }

      if (a < CV_PI / 8 || a > CV_PI - CV_PI / 8) {
        if (m > magnitudes.at<float>(y, x + 1) &&
            m > magnitudes.at<float>(y, x - 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else if (a < 0.5f * CV_PI - CV_PI / 8) {
        if (m > magnitudes.at<float>(y - 1, x + 1) &&
            m > magnitudes.at<float>(y + 1, x - 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else if (a < 0.5f * CV_PI + CV_PI / 8) {
        if (m > magnitudes.at<float>(y - 1, x) &&
            m > magnitudes.at<float>(y + 1, x)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else {
        if (m > magnitudes.at<float>(y - 1, x - 1) &&
            m > magnitudes.at<float>(y + 1, x + 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      }
    }
  }

Float32 input.
image description

OpenCV's Canny output

cv::Canny(input, output, 100, 200, 3, true);

image description

My
image description

Next steps of method only reduces number of edge pixels. Thus my mistake already here.
Based on OpenCV 3.2.x doc and OpenCV 2.4.x doc.
Version of Opencv: 3.1.0-dev

Please tell me if I have obvious misunderstanding. Thanks!


Update: Problem solved, removed gaussian blur (not used in OpenCV's implementation) and edited conditions (two '>' replaced to '>=' and swapped diagonals).

  cv::Sobel(blur, dx, CV_32F, 1, 0, 3);
  cv::Sobel(blur, dy, CV_32F, 0, 1, 3);
  cv::cartToPolar(dx, dy, magnitudes, angles);

  cv::Mat edges = cv::Mat::zeros(img.size(), CV_8UC1);
  for (int y = 1; y < angles.rows - 1; ++y) {
    for (int x = 1; x < angles.cols - 1; ++x) {
      float a = angles.at<float>(y, x);
      float m = magnitudes.at<float>(y, x);
      if (a > CV_PI) {
        a -= CV_PI;
      }

      if (a < CV_PI / 8 || a > CV_PI - CV_PI / 8) {
        if (m >= magnitudes.at<float>(y, x + 1) &&
            m > magnitudes.at<float>(y, x - 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else if (a < 0.5f * CV_PI - CV_PI / 8) {
        if (m > magnitudes.at<float>(y - 1, x - 1) &&
            m > magnitudes.at<float>(y + 1, x + 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else if (a < 0.5f * CV_PI + CV_PI / 8) {
        if (m > magnitudes.at<float>(y - 1, x) &&
            m >= magnitudes.at<float>(y + 1, x)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      } else {
        if (m > magnitudes.at<float>(y - 1, x + 1) &&
            m > magnitudes.at<float>(y + 1, x - 1)) {
          edges.at<uint8_t>(y, x) = 255;
        }
      }
    }
  }
edit retag flag offensive close merge delete

Comments

I have found this article with "Linking of the Anchors by Smart Routing" procedure. I will try it.

dkurtaev gravatar imagedkurtaev ( 2016-12-26 07:49:06 -0500 )edit