{
// 1. Gaussian blurring
Mat gauImg;
GaussianBlur(*pSrcImg, gauImg, Size(5, 5), 0);
if (debug)
{
imshow("gaussian", gauImg);
cv::waitKey(0);
}
Mat grayImg;
if (gauImg.channels() == 3)
cvtColor(gauImg, grayImg, COLOR_BGR2GRAY);
else
grayImg = gauImg.clone();
if (debug)
{
imshow("gray", grayImg);
cv::waitKey(0);
}
// 2. calc gradient angle and magnitude
Mat sobxImg, sobyImg, angleImg_orig, angleImg, magImg;
Sobel(grayImg, sobxImg, CV_32FC1, 1, 0);
Sobel(grayImg, sobyImg, CV_32FC1, 0, 1);
if (debug)
{
imshow("sobel x", sobxImg);
imshow("sobel y", sobyImg);
cv::waitKey(0);
}
cartToPolar(sobxImg, sobyImg, magImg, angleImg_orig, true);
// normal angleImg_orig(angle value: 0~360) to angleImg( angle value: [0, 45, 90, 135])
angleImg = Mat(angleImg_orig.size(), CV_8UC1);
for (int row = 0; row < angleImg_orig.rows; row++)
{
for (int col = 0; col < angleImg_orig.cols; col++)
{
if ((angleImg_orig.at<float>(row, col) >= 0 && angleImg_orig.at<float>(row, col) < 22.5) ||
(angleImg_orig.at<float>(row, col) >= 337.5 && angleImg_orig.at<float>(row, col) < 360) ||
angleImg_orig.at<float>(row, col) >= 157.5 && angleImg_orig.at<float>(row, col) < 202.5)
{
angleImg.at<uchar>(row, col) = 0;
}
else if ((angleImg_orig.at<float>(row, col) >= 22.5 && angleImg_orig.at<float>(row, col) < 67.5) ||
(angleImg_orig.at<float>(row, col) >= 202.5 && angleImg_orig.at<float>(row, col) < 247.5))
{
angleImg.at<uchar>(row, col) = 45;
}
else if ((angleImg_orig.at<float>(row, col) >= 67.5 && angleImg_orig.at<float>(row, col) < 112.5) ||
(angleImg_orig.at<float>(row, col) >= 247.5 && angleImg_orig.at<float>(row, col) < 292.5))
{
angleImg.at<uchar>(row, col) = 90;
}
else
{
angleImg.at<uchar>(row, col) = 135;
}
}
}
// 3. non-maximum magnitude edge point suppression
Mat nmsImg = Mat::zeros(magImg.size(), CV_8UC1);
Mat nmsMagImg = Mat::zeros(magImg.size(), CV_32FC1);
for (int row = 1; row < - 1; row++)
{
for (int col = 1; col < - 1; col++)
{
if (angleImg.at<uchar>(row, col) == 0 &&
(magImg.at<float>(row, col) > magImg.at<float>(row, col - 1) &&
magImg.at<float>(row, col) > magImg.at<float>(row, col + 1)))
{
nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);
nmsImg.at<uchar>(row, col) = 255;
continue;
}
if (angleImg.at<uchar>(row, col) == 45 &&
(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col + 1) &&
magImg.at<float>(row, col) > magImg.at<float>(row + 1, col - 1)))
{
nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);
nmsImg.at<uchar>(row, col) = 255;
continue;
}
if (angleImg.at<uchar>(row, col) == 90 &&
(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col) &&
magImg.at<float>(row, col) > magImg.at<float>(row + 1, col)))
{
nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);
nmsImg.at<uchar>(row, col) = 255;
continue;
}
if (angleImg.at<uchar>(row, col) == 135 &&
(magImg.at<float>(row, col) > magImg.at<float>(row - 1, col - 1) &&
magImg.at<float>(row, col) > magImg.at<float>(row + 1, col + 1)))
{
nmsMagImg.at<float>(row, col) = magImg.at<float>(row, col);
nmsImg.at<uchar>(row, col) = 255;
continue;
}
}
}
if (debug)
{
imshow("nms", nmsImg);
imshow("nms mag", nmsMagImg);
cv::waitKey(0);
}
// 4. filter out edge points by low theshold and high threshold
// 4.1 judge strong edge point: nmxMagImg pixel value > hightThres
// judge weakge edge point: nmxMagImg pixel value < lowThres
// note: if use magImg to judge, result image will like threshold() output image - rough edge
Mat result = nmsImg.clone();
for (int row = 1; row < - 1; row++)
{
for (int col = 1; col < - 1; col++)
{
if (nmsMagImg.at<float>(row, col) >= highThres)// note: must be nmsMagImg, not be magImg
{
result.at<uchar>(row, col) = 255;
}
if (nmsMagImg.at<float>(row, col) < lowThres)
{
result.at<uchar>(row, col) = 0;
}
}
}
if (debug)
{
imshow("strong edge", result);
cv::waitKey(0);
}
// .4.2 judge medium edge points : lowThres< nmsMagImg pixel value <hightThres
for (int row = 1; row < - 1; row++)
{
for (int col = 1; col < - 1; col++)
{
if (nmsMagImg.at<float>(row, col) >= lowThres && nmsMagImg.at<float>(row, col) < highThres)
{
if (result.at<uchar>(row - 1, col - 1) == 255 || result.at<uchar>(row - 1, col) == 255 ||
result.at<uchar>(row - 1, col + 1) == 255 || result.at<uchar>(row, col + 1) == 255 ||
result.at<uchar>(row + 1, col + 1) == 255 || result.at<uchar>(row + 1, col) == 255 ||
result.at<uchar>(row + 1, col - 1) == 255 || result.at<uchar>(row, col - 1) == 255)
{
result.at<uchar>(row, col) = 255;
}
else
{
result.at<uchar>(row, col) = 0;
}
}
}
}
if (debug)
{
imshow("my canny", result);
cv::waitKey(0);
}
}