感谢
opencv 五 缺陷检测实战1(检测以连通域面积特征为缺陷)_opencv 缺陷检测-CSDN博客
代码实现
main函数
#include<iostream>
#include<opencv.hpp>
#include<string>
#include"Processing.h"
using namespace std;
using namespace cv;
int main() {
String image_path = "./image/原图.png";
Mat src = imread(image_path);
if (src.empty()) {
cout << "没有图片" << endl;
return 0;
}
imshow("输入", src);
Processing img_processing;
Mat img_re_processing = img_processing.re_processing(src);
Mat img_connection = img_processing.connection_check(img_re_processing);
// imshow("缺陷标记", img_connection);
copyTo(img_connection, src, img_connection);
imshow("缺陷检测", src);
imwrite("./result/运行结果.png", src);
waitKey(0);
return 0;
}
构建图像处理类Processing
Processing.h
#pragma once
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class Processing
{
public:
//图片预处理(降噪、灰度图、二值化)
Mat re_processing(Mat& image);
//连通域检测
Mat connection_check(Mat& image);
};
Processing.cpp
#include "Processing.h"
Mat Processing::re_processing(Mat& image) {
//转灰度图
Mat image_gray;
if (image.type() != CV_8U) {
cvtColor(image, image_gray, CV_8U);
}
if (image.channels() == 3) {
cvtColor(image_gray, image_gray, COLOR_BGR2GRAY);
}
else {
image_gray = image.clone();
}
//去噪
Mat image_denoising;
medianBlur(image_gray, image_denoising, 5);
GaussianBlur(image_denoising, image_denoising, Size(5, 5), 0);
//二值化
Mat image_bin;
const int maxVal = 255;
int threshType = 0;
threshold(image_denoising, image_bin, 128, 255, THRESH_OTSU);
image_bin = 255 - image_bin;
// 腐蚀
return image_bin;
}
Mat Processing::connection_check(Mat& image) {
// 连通域检测
Mat labels = Mat::zeros(image.size(), image.type());
Mat stats, centroids;
int num = connectedComponentsWithStats(image, labels, stats, centroids);
if (num == 0) {
cout << "无连通域" << endl;
return labels;
}
else {
cout << "检测到连通域,数量:" << num << endl;
}
// 遍历所有连通域,面积大于所有连通域面积平均值的为缺陷
// 求均值
int area_all = 0;
int max_area = 0;
for (int i = 1; i < num; i++) {
int area = stats.at<int>(i, CC_STAT_AREA);
cout << "NO. : " << i << " 面积:" << area << endl;
area_all += area;
}
int area_mean = area_all / num;
cout << "平均面积: " << area_mean << endl;
//Mat mask = Mat::zeros(image.size(), image.type());
Mat display = Mat::zeros(image.size(), CV_8UC3);
for (int i= 1; i < num; i++) {
int area = stats.at<int>(i, CC_STAT_AREA);
if (area > area_mean) {
Mat mask = (labels == i);
display.setTo(Scalar(0, 0, 255), mask);
}
}
return display;
}