Ask Your Question
1

Canny using separate functions

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

dkurtaev gravatar image

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

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

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-12-26 07:49:06 -0600

dkurtaev gravatar image

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

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-12-26 03:48:17 -0600

Seen: 478 times

Last updated: Dec 27 '16