您的位置:首页 > 运维架构

opencv——自适应阈值Canny边缘检测

2021-06-03 14:28 851 查看

前言

Canny边缘检测速度很快,OpenCV中经常会用到Canny边缘检测,以前的Demo中使用Canny边缘检测都是自己手动修改高低阈值参数,最近正好要研究点小东西时,就想能不能做个自适应的阈值,在不影响整体效果的基础上不用手动调参,话不多说,且看下文。

 实现思路:

  1. 图像转成灰度图像
  2. 求其灰度直方图,并找出中位数
  3. 根据中位数和设定的sigma值求出高低阈值
  4. 使用Canny边缘检测

代码实现:

int main()
{
int GetMatMidVal(Mat& img);
void GetMatMinMaxThreshold(Mat& img, int& minval, int& maxval, float sigma);
Mat src = imread("D:/opencv练习图片/灰度图片.png");
imshow("原图", src);
Mat gray,binary_1,binary_2;
cvtColor(src, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(3, 3), 0.5, 0.5);
int minthreshold, maxthreshold;
GetMatMinMaxThreshold(gray, minthreshold, maxthreshold,0.2);
cout << "min:" << minthreshold << "  max:" << maxthreshold << endl;
Canny(gray, binary_1, minthreshold, maxthreshold);
imshow("自适应边缘", binary_1);
//Canny(gray, binary_2, 100, 200, 3);
//imshow("边缘", binary_2);
waitKey(0);
return 0;
}

//求Mat的中位数
int GetMatMidVal(Mat& img)
{
//判断如果不是单通道直接返回128
if (img.channels() > 1) return 128;
int rows = img.rows;
int cols = img.cols;
//定义数组
float mathists[256] = { 0 };
//遍历计算0-255的个数
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
int val = img.at<uchar>(row, col);
mathists[val]++;
}
}
int calcval = rows * cols / 2;
int tmpsum = 0;
for (int i = 0; i < 255; ++i) {
tmpsum += mathists[i];
if (tmpsum > calcval) {
return i;
}
}
return 0;
}

//求自适应阈值的最小和最大值
void GetMatMinMaxThreshold(Mat& img, int& minval, int& maxval, float sigma)
{
int midval = GetMatMidVal(img);
cout << "midval:" << midval << endl;
// 计算低阈值
minval = saturate_cast<uchar>((1.0 - sigma) * midval);
//计算高阈值
maxval = saturate_cast<uchar>((1.0 + sigma) * midval);
}

结论:

 从上图中可以看出,命令行窗口中min和max就是求出的高低阈值,使用Canny边缘检测时直接就按这两个高低阈值处理的。对于灰度图像,效果较好。

严谨性不高,后续仍需改进!!😀😀😀

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: