主要参考:主要参考
原文是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
#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;
}