Ask Your Question
1

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

1 answer

Sort by ยป oldest newest most voted
0

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

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
Login/Signup to Answer

Question Tools

1 follower

Stats

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

Seen: 185 times

Last updated: Dec 27 '16