BS版图形系统 - OpenCV - 第5章笔记
- 5 自动光学检查、对象分割和检测
- 5.1 技术要求
- 5.2 隔离场景中的对象
- 5.3 为AOI创建应用程序
- 5.4 预处理输入图像
- 5.4.1 噪声消除
- 5.4.2 用光模式移除背景进行分割
- 5.4.3 阈值
- 5.5 分割输入图像
- 5.5.1 连通组件算法
- 5.5.2 findContours算法
- 5.6 总结
5 自动光学检查、对象分割和检测
AOI:自动光学检查
5.1 技术要求
5.2 隔离场景中的对象
- 预处理:
- 噪声消除
- 光消除
- 二值化
- 分割:
- 轮廓检测
- 连通组件提取(标签)
5.3 为AOI创建应用程序
输入参数:
- 要处理的输入图像
- 光图像模式
- 光操作,用户可以选择减法或除法运算
- 值0,采用减法操作
- 值1,采用除法操作
- 分割:在有无统计信息的情况下连通组件之间进行选择,并找到画轮廓线的方法
5.4 预处理输入图像
最大程度减少由于相机镜头引起的图像噪声、光线条件与图像变形
5.4.1 噪声消除
- 高斯噪声、尖峰噪声、散粒噪声
- 椒盐噪声:
- 中值滤波器常用于去除椒盐噪声,以丢失小的细节
- 盒式滤波器或高斯滤波器,噪声不会被消除,但会变得平滑,对象细节也会丢失和变平滑
- 中值滤波器:medianBlur(img, img_noise, 3)
5.4.2 用光模式移除背景进行分割
- 基本阈值,伪影有很多白噪声
- 期望的背景移除和阈值处理结果
- 做法:准备一张没有任何对象的场景图片,然后采用减法或除法操作
- 减法:R = L - I
- 除法:R = 255 * (1 - (I / L))
Mat removeLight(Mat img, Mat pattern, int method)
{
Mat aux;
// if method is normalization
if(method==1)
{
// Require change our image to 32 float for division
Mat img32, pattern32;
img.convertTo(img32, CV_32F);
pattern.convertTo(pattern32, CV_32F);
// Divide the imabe by the pattern
aux= 1-(img32/pattern32);
// Convert 8 bits format
aux.convertTo(aux, CV_8U, 255);
}else{
aux= pattern-img;
}
//equalizeHist( aux, aux );
return aux;
}
- 创建光/背景模式:使用过滤器,应用于输入图像的大内核尺寸的模糊技术
Mat calculateLightPattern(Mat img)
{
Mat pattern;
// Basic and effective way to calculate the light pattern from one image
blur(img, pattern, Size(img.cols/3,img.cols/3));
return pattern;
}
5.4.3 阈值
Mat img_thr;
if(method_light!=2){
threshold(img_no_light, img_thr, 30, 255, THRESH_BINARY);
}else{
threshold(img_no_light, img_thr, 140, 255, THRESH_BINARY_INV);
}
5.5 分割输入图像
两种技术:连通组件、查找轮廓
ROI:感兴趣区域
5.5.1 连通组件算法
- connectedComponents
void ConnectedComponents(Mat img)
{
// Use connected components to divide our possibles parts of images
Mat labels;
auto num_objects= connectedComponents(img, labels);
// Check the number of objects detected
if(num_objects < 2 ){
cout << "No objects detected" << endl;
return;
}else{
cout << "Number of objects detected: " << num_objects - 1 << endl;
}
// Create output image coloring the objects
Mat output= Mat::zeros(img.rows,img.cols, CV_8UC3);
RNG rng( 0xFFFFFFFF );
for(auto i=1; i<num_objects; i++){
Mat mask= labels==i;
output.setTo(randomColor(rng), mask);
}
//imshow("Result", output);
miw->addImage("Result", output);
}
- Stats算法
void ConnectedComponentsStats(Mat img)
{
// Use connected components with stats
Mat labels, stats, centroids;
auto num_objects= connectedComponentsWithStats(img, labels, stats, centroids);
// Check the number of objects detected
if(num_objects < 2 ){
cout << "No objects detected" << endl;
return;
}else{
cout << "Number of objects detected: " << num_objects - 1 << endl;
}
// Create output image coloring the objects and show area
Mat output= Mat::zeros(img.rows,img.cols, CV_8UC3);
RNG rng( 0xFFFFFFFF );
for(auto i=1; i<num_objects; i++){
cout << "Object "<< i << " with pos: " << centroids.at<Point2d>(i) << " with area " << stats.at<int>(i, CC_STAT_AREA) << endl;
Mat mask= labels==i;
output.setTo(randomColor(rng), mask);
// draw text with area
stringstream ss;
ss << "area: " << stats.at<int>(i, CC_STAT_AREA);
putText(output,
ss.str(),
centroids.at<Point2d>(i),
FONT_HERSHEY_SIMPLEX,
0.4,
Scalar(255,255,255));
}
imshow("Result", output);
miw->addImage("Result", output);
}
5.5.2 findContours算法
- 参数:
- Image: 灰度输入图像
- Contours: 轮廓输出,其中每个检测到的轮廓点是点的向量
- Hierarchy:可选的输出向量,用于保存轮廓的层次结构
- Mode: 检索轮廓的模式
- Method:用近似方法来检索轮廓的形状
- Offset:移动所有轮廓的可选点值
输入图像会被findContours函数修改
drawContours
5.6 总结