您的位置:首页 > 其它

网格缺陷检测(二值化阈值分析)

2021-06-04 17:30 696 查看

摘要

本篇来用OpenCV实现Halcon中一个简单的网格缺陷检测实例。 Halcon中对应的例子为novelty_detection_dyn_threshold.hdev。并对二值化中的三种阈值处理进行介绍和比较:

  • 全局阈值二值化(含OTSU方法)
  • 自适应阈值二值化

  • 双阈值二值化

阈值处理分析

1️⃣全局阈值二值化-threshold()

OpenCV的threshold函数一般是给定一个阈值,对超过或者低于这个阈值的像素进行处理,函数如下:

threshold(
InputArray src,      // 输入图像
OutputArray dst,     // 输出图像
double thresh,       // 阈值
double maxValue,     // 最大值(对于三通道图像一般是255)
int thresholdType    // 阈值化操作的类型
)
阈值化操作的类型常用两种:
THRESH_BINARY     //黑背景找白目标(即超过设定阈值的值置255,其他为0)
THRESH_BINARY_INV //白背景找黑目标(即超过设定阈值的值置0,其他为255)

 全局阈值类似一刀切的概念。对于整体图像来说,找到一个合适的阈值,将图像分为0(黑色)和255(白色)。

2️⃣自适应阈值二值化-adaptiveThreshold()

对于亮度分布差异较大的图像,因为常常无法找到一个合适的阈值。因此我们需要一种改进的阈值化算法,即自适应阈值化。

adaptiveThreshold(
InputArray src,       // 输入图像
OutputArray dst,      // 输出图像
double maxValue,      // 最大值
int adaptiveMethod,   // 自适应方法,平均或高斯
int thresholdType     // 阈值化类型
int blockSize,        // 块大小(大小必须为奇数)
double C              // 常量(即偏移值调整
56c
量)
)
//adaptiveThreshold()支持两种自适应方法:
ADAPTIVE_THRESH_MEAN_C       //平均:阈值是邻域的平均值
ADAPTIVE_THRESH_GAUSSIAN_C //高斯:阈值是邻域值的加权和,其中权重是高斯窗口

 自适应阈值化能够根据图像不同区域亮度分布的,改变阈值。因此,我们针对同一图像的不同区域获得不同的阈值,并为具有不同照明的图像提供更好的结果。

 3️⃣双阈值二值化

对于图像具有明显的双分界特征,可以使用双阈值法进行二值化操作,即实现Halcon中的threshold函数。

简单来说:

  • Halcon的threshold函数是获取区间[a, b]之间的灰度值(双阈值)
  • OpenCV的threshold只能针对大于或者小于a或者b的灰度值处理(单阈值)

因此我们可以预设两个特定的阈值量thresh1、thresh2,并且thresh1 < thresh2 。阈值化的过程就是,将在 (thresh1,thresh2) 这个区间内的灰度值设置为maxVal(255),将其余 ad8 部分设置为0 。

const int maxVal = 255;        //预设最大值
int low_threshold = 90;        //较小的阈值量
int high_threshold = 190;      //较大的阈值量
//小阈值对源灰度图像进行二进制阈值化操作
threshold(srcGray, dst1, low_threshold, maxVal, THRESH_BINARY);
//大阈值对源灰度图像进行反二进制阈值化操作
threshold(srcGray, dst2, high_threshold, maxVal, THRESH_BINARY_INV);
//矩阵"与运算"得到二值化结果
bitwise_and(dst1, dst2, dst); //对像素加和
imshow("双阈值二值化", dst);
程序中主要还是用到了threshold()函数,对较小的阈值量进行二进制阈值化,而对较大的阈值量进行反二进制化操作,最后将所得的两幅图像进行与运算,得到最终效果。

网格缺陷检测

进入正题,本篇对网格缺陷检测的思路很简单:

  1. 动态阈值处理
  2. 面积筛选显示缺陷

opencv实现:

Mat src = imread("D:/opencv练习图片/网格缺陷检测1.png");
imshow("原图", src);
cvtColor(src, gray, COLOR_RGB2GRAY);
GaussianBlur(gray, gray, Size(3, 3), 1, 0);
//双阈值方法
threshold(gray, binary1, 25, 255, THRESH_BINARY);
threshold(gray, binary2, 80, 255, THRESH_BINARY_INV);
bitwise_and(binary1, binary2, binary);
imshow("双阈值二值化", binary);
vector<vector<Point>>contours;
findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
for (int i = 0; i < contours.size(); i++)
{
float area = contourArea(contours[i]);
if (area>350)
{
drawContours(src, contours, i, Scalar(0, 0, 255), 2, 8);
int baseline = 0;
Size textSize = getTextSize("Mesh Not OK", FONT_HERSHEY_SIMPLEX, 1.0, 2, &baseline);
rectangle(src, Rect(10, 10, textSize.width, textSize.height + baseline), Scalar(212, 233, 252), -1, 8);
putText(src, "Mesh Not OK", Point(10, 5 + textSize.height + baseline), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255), 2, 8);
}
else
{
int baseline = 0;
Size textSize = getTextSize("Mesh OK", FONT_HERSHEY_SIMPLEX, 1.0, 2, &baseline);
rectangle(src, Rect(10, 10, textSize.width, textSize.height + baseline), Scalar(212, 233, 252), -1, 8);
putText(src, "Mesh OK", Point(10, 5 + textSize.height + baseline), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255), 2, 8);
}
}
imshow("缺陷", src);

这里采用的是双阈值处理。我们可以对比三种阈值处理的情况:

(1)全局阈值OTSU方法:

 可以看到有部分正常孔洞和网格相连,会导致正常孔洞也被标记为缺陷。

(2)自适应阈值:

 可以看到效果还不错。

(3)双阈值:

 对比自适应阈值,可以看到分割的还是比较明显一点的。

 参考博文:python-opencv函数总结之(一)threshold、adaptiveThreshold、Otsu 二值化_sinat_21258931的博客-CSDN博客

                 OpenCV与AI深度学习

 

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