今天看见一篇论文,关于轴承滚动体缺陷检测的,滚动体有三种缺陷类型:缺簧、缺珠、缺簧缺珠。作者写的很详细,于是就跟着作者的方法介绍开始复现过程,若侵权请联系我删除。
步骤:
- 灰度增强
- 阈值分割
- 圆径向搜索
- 构造掩模
- ROI分割
- 连通域检测筛选
其中有两点之前没有接触到,记录一下。
1. 灰度增强
作者使用公式:
其中,r为原图像灰度,k改变对比度系数,t改变灰度阶级,c改变亮度值,可以提高目标与背景的对比度,然后使用阈值分割可以更好地分割前景。
//灰度增强
for (int i = 0; i < gray.cols; i++) {
for (int j = 0; j < gray.rows; j++) {
double k = gray.at<uchar>(j,i);
// cout << k << endl;
if (k <90)
gray.at<uchar>(j, i) = 0.5 * pow(k, -5)+10;
else {
if (k > 110)
gray.at<uchar>(j, i) = 255;
}
}
}
2. 圆径向搜索
当圆轮廓边缘有较大干扰或者是残缺时,直接使用轮廓点进行圆拟合,会导致较大的拟合误差,通过圆径向搜索可以实现轮廓关键点抓取,进而拟合出圆心和半径,如图所示:
可以通过半径径向去搜索到圆的边缘关键点,但也会出现干扰点,可以通过半径值检测去除,提高拟合精度。
公式为:
不过,初始点圆心必须设置在园内。
//搜索圆
float radius = 100;
const float pi = 3.14159;
float angle = 10 * pi / 180;
float angles = 360 * pi / 180;
Point2f A;
Point2f O;
O.x = gray.cols / 2;
O.y = gray.rows / 2;
vector<Point2f>B,L;
for (angle; angle < angles; angle = angle + 0.5) {
for (int i = 20; i < radius; i++) {
A.x = int(O.x + i*cos(angle));
A.y = int(O.y - i*sin(angle));
if (!binary.at<uchar>(A.y, A.x)) {
B.push_back(Point(A.x, A.y));
break;
}
}
}
结果:
至于擦伤、磕伤、边缘缺损等也可以通过提取两个圈的圆环进行检测。