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 隔离场景中的对象

opencv HSV 高光_opencv HSV 高光


opencv HSV 高光_html5_02

  • 预处理:
  • 噪声消除
  • 光消除
  • 二值化
  • 分割:
  • 轮廓检测
  • 连通组件提取(标签)

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;
}

opencv HSV 高光_opencv HSV 高光_03

  • 创建光/背景模式:使用过滤器,应用于输入图像的大内核尺寸的模糊技术
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);
}

opencv HSV 高光_预处理_04

  • 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);
}

opencv HSV 高光_opencv_05

5.5.2 findContours算法

  • 参数:
  • Image: 灰度输入图像
  • Contours: 轮廓输出,其中每个检测到的轮廓点是点的向量
  • Hierarchy:可选的输出向量,用于保存轮廓的层次结构
  • Mode: 检索轮廓的模式
  • Method:用近似方法来检索轮廓的形状
  • Offset:移动所有轮廓的可选点值
    输入图像会被findContours函数修改
    drawContours

5.6 总结

opencv HSV 高光_opencv HSV 高光_06