opencv c++ 传统瑕疵检测简例

opencv c++ 传统瑕疵检测

主要参考:主要参考

原文是python版本,本文改写c++版本。

算法过程

1️⃣首先是图像二值化,之后开运算(先腐蚀,再膨胀)去噪。

	Mat gray;
	cvtColor(src, gray,COLOR_BGR2GRAY);
	Mat gray_binary;
	threshold(gray, gray_binary, 0, 255, cv::THRESH_BINARY_INV| THRESH_OTSU);

	Mat se = getStructuringElement(MORPH_RECT,Size(3,3),Size(-1,-1));
	Mat binary;
	morphologyEx(gray_binary, binary, MORPH_OPEN, se);
	imshow("gray_binary", binary);

在这里插入图片描述

2️⃣之后查找轮廓并以第一个为模板(因为默认第一个为标准件)

	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binary, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE);
	int height = src.rows,weidth=src.cols;
	vector<Rect2i> rects;
	for(int i=0;i<contours.size();i++)
	{
		Rect2i rec = boundingRect(contours[i]);
		double area = contourArea(contours[i]);
		if (rec.height > height / 2)continue;
		if (area < 150)continue;
		rects.push_back(rec);
	}

	rects = sort_boxes(rects);
	Mat temp = get_template(binary,rects);

在这里插入图片描述

3️⃣轮廓填充(填充外接矩形)

for (int i=0;i<contours.size();i++)
	{	
		Rect2i rec = boundingRect(contours[i]);
		double area = contourArea(contours[i]);
		if (rec.height > height / 2)continue;
		if (area < 150)continue;
		drawContours(binary, contours, i, (0), 2, 8);
	}

之后是图像相减并保存差结果大的部分作为坏件输出。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

具体请看参考贴。

总体代码

#include <opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;
# define threhold 30
vector<Rect2i> sort_boxes(vector<Rect2i>& input);
Mat get_template(Mat binary, vector<Rect2i> rects);
vector<Rect2i> detect_defect(Mat binary, vector<Rect2i> rects, Mat temp);

int main()
{

	Mat src = imread("D:\\code\\LearnOpenCV\\2.jpg");
	if (src.empty()) {
		printf("could not find the image!\n");
		return -1;
	}

	Mat gray;
	cvtColor(src, gray,COLOR_BGR2GRAY);
	Mat gray_binary;
	threshold(gray, gray_binary, 0, 255, cv::THRESH_BINARY_INV| THRESH_OTSU);

	Mat se = getStructuringElement(MORPH_RECT,Size(3,3),Size(-1,-1));
	Mat binary;
	morphologyEx(gray_binary, binary, MORPH_OPEN, se);
	imshow("gray_binary", binary);

	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binary, contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE);
	int height = src.rows,weidth=src.cols;
	vector<Rect2i> rects;
	for(int i=0;i<contours.size();i++)
	{
		Rect2i rec = boundingRect(contours[i]);
		double area = contourArea(contours[i]);
		if (rec.height > height / 2)continue;
		if (area < 150)continue;
		rects.push_back(rec);
	}

	rects = sort_boxes(rects);
	Mat temp = get_template(binary,rects);

	for (int i=0;i<contours.size();i++)
	{	
		Rect2i rec = boundingRect(contours[i]);
		double area = contourArea(contours[i]);
		if (rec.height > height / 2)continue;
		if (area < 150)continue;
		drawContours(binary, contours, i, (0), 2, 8);
	}
	/*int index = 1;
	for (int i = 0; i < rects.size(); i++)
	{
		Rect2i tmp = rects[i];
		string out = "nums: " + to_string((int)index++);
		putText(src, out, Point(tmp.x - 40, tmp.y + 15), FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0), 1);
	}
	imshow("res1", src);*/
	vector<Rect2i> defect_boxes = detect_defect(binary, rects, temp);
	cout <<"defect_boxes.size: " << defect_boxes.size() << endl;
	for (int i = 0; i < defect_boxes.size(); i++)
	{
		Rect2i tmp = defect_boxes[i];
		rectangle(src, Point(tmp.x, tmp.y), Point(tmp.x + tmp.width, tmp.y + tmp.height), (0, 0, 255),1,8,0);
		putText(src, "bad", Point(tmp.x, tmp.y), FONT_HERSHEY_PLAIN, 1.0, (0, 255, 0), 2);
	}
	 int index = 1;
	for (int i = 0; i < rects.size(); i++)
	{
		Rect2i tmp = rects[i];
		string out = "nums: " + to_string((int)index++);
		putText(src, out, Point(tmp.x - 40, tmp.y + 15), FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0), 1);
	}
	imshow("res", src);
	waitKey(0);
	return 0;
}

vector<Rect2i> sort_boxes(vector<Rect2i>& input) {
	for (int i = 0; i < input.size() - 1; i++)
	{
		for (int j = i; j < input.size(); j++)
		{
			Rect2i tmp = input[j];
			if (tmp.y < input[i].y)
			{
				Rect2i tmp2 = input[i];
				input[i] = input[j];
				input[j] = tmp2;
			}
		}
	}
	return input;
}

Mat get_template(Mat binary, vector<Rect2i> rects) {
	Mat roi = binary(rects[0]);
	return roi;
}

vector<Rect2i> detect_defect(Mat binary, vector<Rect2i> rects, Mat temp)
{
	int height = temp.rows, weight = temp.cols;
	vector<Rect2i> defect_rois;
	for (int i = 0; i < rects.size(); i++) 
	{
		Mat roi = binary(rects[i]);
		Rect2i tmp = rects[i];
		/*rectangle(binary, Point(tmp.x, tmp.y), Point(tmp.x + tmp.width, tmp.y + tmp.height), (0, 0, 255), 1, 8, 0);
		imshow("res", binary);
		waitKey(500);*/
		resize(roi,roi,temp.size());
		Mat mask;
		subtract(temp, roi, mask);
		Mat se = getStructuringElement(MORPH_RECT, Size(3, 3), Size(-1, -1));
		morphologyEx(mask,mask, MORPH_OPEN, se);
		threshold(mask, mask, 0, 255, THRESH_BINARY);
		imshow("res", mask);
		waitKey(500); 
		int count = 0;
		for (int i1= 0; i1 < temp.rows; i1++)
		{
			for (int j1 = 0; j1 < temp.cols; j1++)
			{
				auto pv = mask.at<uchar>(i1,j1);
				if (pv == 255)count += 1;
			}
		}
	
		if (count > threhold)
		{
			defect_rois.push_back(rects[i]);
			cout <<"tes: "<< i << endl;
		}
	}
	return defect_rois;

}
  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wdmcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值