BS版图形系统 - OpenCV - 第5章笔记


** QQ: 282397369 **

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 总结

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值