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

opencv c++ 传统瑕疵检测简例_第1张图片

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

opencv c++ 传统瑕疵检测简例_第2张图片

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

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

opencv c++ 传统瑕疵检测简例_第3张图片

具体请看参考贴。

总体代码

#include 
#include

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;

}

你可能感兴趣的:(opencv,c++,计算机视觉)