OpenCV C++案例实战三十三《缺陷检测》

这篇具有很好参考价值的文章主要介绍了OpenCV C++案例实战三十三《缺陷检测》。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本案例将使用OpenCV C++ 进行PCB印刷缺陷检测。目前缺陷检测算法可分为两大类:
一:基于模板匹配的缺陷检测
二:基于深度学习的缺陷检测,主要利用目标检测去识别缺陷部分。
本文算法主要是基于模板匹配算法进行缺陷检测,参考《基于差异模型的印刷标签缺陷检测算法》一文,进行算法复现,感兴趣的朋友可以去阅读一下原文。
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

一、结果演示

OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

二、缺陷检测算法

2.1、多元模板图像

通过工业相机采集合格标签图像,作为差异模型的训练数 据集,选择其中一张合格标签图像分别进行高斯平滑、灰度腐蚀 和灰度膨胀操作,获取多元模板图像,用于训练差异模型。
将合格图像f(x,y)与高斯核滤波器卷积,得到高斯平滑图像f1(x,y)。 构建一个11×11大小的矩形结构元素,对合格标签图像进 行灰度腐蚀运算,得到灰度腐蚀图像f2(x,y)。再构建一个13×13 大小的矩形结构元素,对合格标签图像进行灰度膨胀运算[3],得到灰度膨胀图像f3(x,y)。

2.2、训练差异模型

将多元模板图像f1(x,y)、f 2(x,y)与f 3(x,y)作为训练数据集 对差异模型进行训练。对所有图像同一坐标的像素点计算平均 值与标准差[4],得到均值图像F(x,y):
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

标准差图像V(x,y):
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

本文中,F(x,y)、V(x,y)即为差异模型训练过程中的标准图 像与差异图像。

为了使理想的差异模型适应正常的工艺误差范围,加入相对阈值VarThreshold=[b u,b l]参数。 其中,b u为上限相对阈 值,bl为下限相对阈值。如图2所示。则两幅阈值图像T u,l(x,y) 计算如下:
亮阈值图像:Tu(x,y)=F(x,y)+ bu* V(x,y)
暗阈值图像:Tl(x,y)=F(x,y)- bl* V(x,y)

将配准对其后的待测图像c(x,y)与差异模型的阈值图像 Tu, l(x,y)进行像素点之间的灰度值对比,当满足如下条件时,即为检测到的缺陷区域。
c(x,y)>Tu(x,y)∨c(x,y)<T l (x,y)

三、图像配准

如图为模板图像
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

如图为待检测图像,我们需要将待检测图像与模板图像进行图像配准。在这里我使用的是基于图像仿射变换进行两幅图像的矫正。关于图像矫正这块就不细说了,可以参考一下我的这篇博文OpenCV C++案例实战四《图像透视矫正》。这里直接上代码
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

3.1 功能源码

//图像定位矫正
bool ImageLocal(cv::Mat srcImg, cv::Mat& warpImg, Point2f SrcAffinePts[])
{
	Mat grayImg;
	if (srcImg.channels() != 1)
	{
		cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);
	}
	else
	{
		grayImg = srcImg.clone();
	}

	Mat blurImg;
	medianBlur(grayImg, blurImg, 5);

	Mat binImg;
	threshold(blurImg, binImg, 10, 255, THRESH_BINARY);
	//namedWindow("binImg", WINDOW_NORMAL);
	//imshow("binImg", binImg);

	vector<vector<Point>>contours;
	findContours(binImg, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	RotatedRect bRect;
	for (int cnt = 0; cnt < contours.size(); cnt++)
	{
		double area = contourArea(contours[cnt]);
		if (area > 1000)
		{
			bRect = minAreaRect(contours[cnt]);
		}
	}

	if (bRect.size.empty())return false;//如果没有找到最小外接矩形,返回false

	//找到最小外接矩形四个顶点
	Point2f srcPoints[4];
	bRect.points(srcPoints);
	//for (int i = 0; i < 4; i++)
	//{
	//	line(srcImg, srcPoints[i], srcPoints[(i + 1) % 4], Scalar(0, 255, 0), 3);
	//}

	//将四个点按照左上、右上、右下、左下进行区分
	int TL, TR, BR, BL;
	double addmax = 0.0, addmin = 999.9, submax = 0.0, submin = 999.9;
	for (int i = 0; i < 4; i++)
	{
		double addval = srcPoints[i].x + srcPoints[i].y;
		double subval = srcPoints[i].x - srcPoints[i].y;
		if (addval > addmax)
		{
			addmax = addval;
			BR = i;
		}
		if (addval < addmin)
		{
			addmin = addval;
			TL = i;
		}
		if (subval > submax)
		{
			submax = subval;
			TR = i;
		}
		if (subval < submin)
		{
			submin = subval;
			BL = i;
		}
	}

	double LeftHeight = EuDis(srcPoints[TL], srcPoints[BL]);
	double RightHeight = EuDis(srcPoints[TR], srcPoints[BR]);
	double MaxHeight = max(LeftHeight, RightHeight);

	double UpWidth = EuDis(srcPoints[TL], srcPoints[TR]);
	double DownWidth = EuDis(srcPoints[BL], srcPoints[BR]);
	double MaxWidth = max(UpWidth, DownWidth);

	//这里使用的顺序是左上、右上、右下、左下顺时针顺序。SrcAffinePts、DstAffinePts要一一对应
	SrcAffinePts[0] = Point2f(srcPoints[TL]);
	SrcAffinePts[1] = Point2f(srcPoints[TR]);
	SrcAffinePts[2] = Point2f(srcPoints[BR]);
	SrcAffinePts[3] = Point2f(srcPoints[BL]);
	Point2f DstAffinePts[4] = { Point2f(0,0),Point2f(MaxWidth,0),Point2f(MaxWidth,MaxHeight),Point2f(0,MaxHeight) };

	Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);

	warpPerspective(srcImg, warpImg, M, Size(MaxWidth, MaxHeight), 1, 0, Scalar::all(0));

	return true;
}

3.1 功能效果

OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

四、多元模板图像

关于如何计算均值图像、差异图像、以及亮、暗阈值图像在下面源码中以复现,具体请阅读源码。

4.1 功能源码

//计算均值图像
void meanImage(cv::Mat gaussianImg, cv::Mat erodeImg, cv::Mat dilateImg, cv::Mat& meanImg)
{
	meanImg = Mat::zeros(gaussianImg.size(), CV_8U);
	for (int i = 0; i < gaussianImg.rows; i++)
	{
		uchar* gData = gaussianImg.ptr<uchar>(i);
		uchar* eData = erodeImg.ptr<uchar>(i);
		uchar* dData = dilateImg.ptr<uchar>(i);
		uchar* mData = meanImg.ptr<uchar>(i);

		for (int j = 0; j < gaussianImg.cols; j++)
		{
			mData[j] = (gData[j] + eData[j] + dData[j]) / 3;
		}
	}
}


//计算差异图像
void diffImage(cv::Mat gaussianImg, cv::Mat erodeImg, cv::Mat dilateImg, cv::Mat meanImg, cv::Mat& diffImg)
{
	diffImg = Mat::zeros(gaussianImg.size(), CV_8U);
	for (int i = 0; i < gaussianImg.rows; i++)
	{
		uchar* gData = gaussianImg.ptr<uchar>(i);
		uchar* eData = erodeImg.ptr<uchar>(i);
		uchar* dData = dilateImg.ptr<uchar>(i);
		uchar* mData = meanImg.ptr<uchar>(i);
		uchar* Data = diffImg.ptr<uchar>(i);

		for (int j = 0; j < gaussianImg.cols; j++)
		{
			Data[j] = sqrt(powf((gData[j] - mData[j]), 2) + powf((eData[j] - mData[j]), 2) + powf((dData[j] - mData[j]), 2) / 3.0);
		}
	}
}


//计算亮、暗阈值图像
void threshImg(cv::Mat meanImg, cv::Mat diffImg,cv::Mat &LightImg,cv::Mat& DarkImg)
{
	double bu = 1.2;
	double bl = 0.8;

	Mat mul_bu, mul_bl;
	multiply(diffImg, bu, mul_bu);
	multiply(diffImg, bl, mul_bl);

	LightImg = Mat::zeros(meanImg.size(), CV_8U);
	DarkImg = Mat::zeros(meanImg.size(), CV_8U);

	for (int i = 0; i < meanImg.rows; i++)
	{
		uchar* mData = meanImg.ptr<uchar>(i);
		uchar* dData = diffImg.ptr<uchar>(i);
		uchar* lData = LightImg.ptr<uchar>(i);
		uchar* DData = DarkImg.ptr<uchar>(i);
		uchar* buData = mul_bu.ptr<uchar>(i);
		uchar* blData = mul_bl.ptr<uchar>(i);

		for (int j = 0; j < meanImg.cols; j++)
		{
			lData[j] = saturate_cast<uchar>(mData[j] + buData[j]);
			DData[j] = saturate_cast<uchar>(mData[j] - blData[j]);
		}
	}
}

如下图为亮阈值图像。
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

如下图为暗阈值图像。
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

五、缺陷检测

以上,我们计算出来了模板的亮、暗阈值图像,主要就是通过与这两幅图像的灰度值进行对比,进而确定缺陷部分。
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能
如图为:将配准对其后的待测图像c(x,y)与差异模型的阈值图像 Tu, l(x,y)进行像素点之间的灰度值对比,当满足如下条件时,即为检测到的缺陷区域。
c(x,y)>Tu(x,y)∨c(x,y)<T l (x,y)

由于此时提取到的缺陷部分是基于仿射矫正后的,故如果需要在原图上显示结果的话,还需要将检测结果进行反变换回去。具体请阅读源码。

5.1 功能源码

//缺陷检测
void DetectImg(cv::Mat warpImg,cv::Mat LightImg, cv::Mat DarkImg, Point2f SrcAffinePts[],cv::Mat decImg, cv::Mat& showImg)
{
	int th = 10;//容差阈值

	Mat resImg = Mat::zeros(warpImg.size(), CV_8U);
	for (int i = 0; i < warpImg.rows; i++)
	{
		uchar* sData = warpImg.ptr<uchar>(i);
		uchar* lData = LightImg.ptr<uchar>(i);
		uchar* dData = DarkImg.ptr<uchar>(i);
		uchar* rData = resImg.ptr<uchar>(i);

		for (int j = 0; j < warpImg.cols; j++)
		{
			//识别缺陷
			if ((sData[j]-th) > lData[j]||(sData[j]+th) < dData[j])
			{
				rData[j] = 255;
			}
		}
	}

	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
	morphologyEx(resImg, resImg, MORPH_OPEN, kernel);

	kernel = getStructuringElement(MORPH_RECT, Size(7, 7));
	dilate(resImg, resImg, kernel);

	//namedWindow("resImg", WINDOW_NORMAL);
	//imshow("resImg", resImg);

	//绘制缺陷结果
	vector<vector<Point>>contours;
	findContours(resImg, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
	for (int t = 0; t < contours.size(); t++)
	{
		if (contourArea(contours[t]) > 50)
		{
			Rect rect = boundingRect(contours[t]);
			rectangle(showImg, rect, Scalar(0, 0, 255), 2);
		}
	}

	//将结果反变换回原图像
	Point2f DstAffinePts[4] = { Point2f(0,0),Point2f(decImg.cols,0),Point2f(decImg.cols,decImg.rows),Point2f(0,decImg.rows) };

	Mat M = getPerspectiveTransform( DstAffinePts, SrcAffinePts);

	warpPerspective(showImg, showImg, M, decImg.size(), 1, 0, Scalar::all(0));
}

六、效果演示

OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能

OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能
OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能
如上图效果所示,与模板图像对比,基本上将待测图像里的缺陷全部检测,而且误检情况很少。上应用到不同物体检测时,需要根据自己的图像数据进行稍小的调参。在这里只是给大家提供一个算法思路,欢迎大家进行交流学习!!!

OpenCV C++案例实战三十三《缺陷检测》,OpenCV C++项目实战,opencv,c++,人工智能
已经开通微信公众号啦!欢迎大家关注呀!公众号会不定期更新OpenCV系列文章以及相关源代码资料等!欢迎大家关注交流学习!


总结

本文使用OpenCV C++ 进行PCB印刷缺陷检测,主要操作有以下几点。
1、将图像进行仿射变换,与模板图像进行配准
2、计算差异图像,得到基于模板的亮、暗阈值图像
3、将待检测图像与亮、暗阈值图像逐像素比较,设定阈值,超出阈值部分的即为缺陷文章来源地址https://www.toymoban.com/news/detail-718893.html

到了这里,关于OpenCV C++案例实战三十三《缺陷检测》的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • opencv 案例05-基于二值图像分析(简单缺陷检测)

    缺陷检测,分为两个部分,一个部分是提取指定的轮廓,第二个部分通过对比实现划痕检测与缺角检测。本次主要搞定第一部分,学会观察图像与提取图像ROI对象轮廓外接矩形与轮廓。 下面是基于二值图像分析的大致流程 读取图像 将图像转换为灰度图,并对其进行二值化处

    2024年02月10日
    浏览(33)
  • MATLAB算法实战应用案例精讲-【图像处理】缺陷检测(附python和matlab实现代码)

    目录 前言 算法原理 什么是缺陷检测 缺陷检测任务 缺陷检测的关键问题

    2023年04月17日
    浏览(38)
  • OpenCV 项目开发实战--对图像中的斑点进行检测(Python、C++代码实现)

    Blob 是图像中一组连接的像素,它们共享一些共同的属性(例如,灰度值)。在上图中,暗连接区域是斑点,斑点检测旨在识别和标记这些区域。 文末附相关测试代码的下载链接 OpenCV 提供了一种基于不同特征检测和过滤斑点的便捷方法。让我们从最简单的例子开始 Python

    2024年02月14日
    浏览(35)
  • YOLOV5应用实战项目:钢材表面缺陷检测(数据集:NEU-CLS)笔记

    本文记录的是YOLOV5的实战笔记,是一个用yolov5检测钢材表面缺陷的实战案例。 主要分为以下几个步骤: 1. 将原始标签xml文件数据处理成yolo要求的txt格式;(Labels标签数据已按照yolo要求的txt格式处理完成,数据集见文中下载方式) 2. 进行yolo模型的文件配置 3. 训练yolo模型

    2024年02月04日
    浏览(35)
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之四 简单行人人体检测效果

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之四 简单行人人体检测效果 一、简单介绍 二、简单行人人体检测效果实现原理 三、简单行人人体检测效果案例实现简单步骤 四、注意事项 Python是一种跨平台的计算机程序设计语言。是一种面向对

    2024年04月26日
    浏览(36)
  • OpenCV(三十三):计算轮廓面积与轮廓长度

    1.介绍轮廓面积与轮廓长度        轮廓面积(Contour Area)是指轮廓所包围的区域的总面积。通常情况下,轮廓面积的单位是像素的平方。         轮廓长度(Contour Length)又称周长(Perimeter),表示轮廓的闭合边界的长度。轮廓的边界可以看作是由一系列相邻像素点组成的

    2024年02月09日
    浏览(27)
  • 基于OpenCV的高压电力检测项目案例

            随着高压电力设施的日益增多,传统的巡检方式已无法满足现代电力系统的需求。为此,我们决定利用计算机视觉技术,特别是 OpenCV库 ,开发一个高压电力检测系统。目标是实现自动化、高精度的电力设备检测,提高巡检效率,降低人工成本 本项目主要包括以下

    2024年02月22日
    浏览(30)
  • opencv缺陷检测

    用传统算法,根据实际工程项目,手把手教你做一个最典型的产品缺陷检测项目案例,虽然这个案例与实际生产还存在一定的差距,但是这个检测流程已经很接近实际生产了。 我们先看一下测试结果: 这个检测的主要需求就是,根据视频流中流水线上的产品,通过每一帧图

    2024年02月05日
    浏览(29)
  • Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别

    目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 一、简单介绍 二、简单进行人脸训练与识别 1、LBPH(Local Binary Patterns Histograms)算法进行人脸训练和识别 2、实现步骤: 3、判断是谁的人脸: 案例中涉及的关键函数说

    2024年04月26日
    浏览(63)
  • OpenCV - C++实战(05) — 颜色检测

    目录 第5章  颜色检测 5.1 实现原理 5.2 Lab颜色模型 5.3 cv :: threshold() 阈值函数  5.4 计算图像之间的距离 5.4.1 公式计算 5.4.2 cv::absdiff() 5.4.3 cv::floodFill()   5.5 完整代码 Github代码地址:GitHub - Qinong/OpenCV         颜色检测用来识别图像中所有像素的某种颜色。这个算法必领输

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包