Canny using separate functions
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.
OpenCV's Canny output
cv::Canny(input, output, 100, 200, 3, true);
My
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;
}
}
}
}