C++ OpenCV踏面缺陷检测
检测出缺陷位置,用矩形框框出,将结果写入xml文件中(voc格式)
·
实现需求
检测出缺陷位置,用矩形框框出,将结果写入xml文件中(voc格式)
将所有矩形框信息写入XML文件
// 将一个矩形框信息写入XML文件
void writeRectangle(std::ofstream& file, const Rectangle& rect) {
file << "\t<object>" << std::endl;
file << "\t\t<name>rectangle</name>" << std::endl;
file << "\t\t<pose>Unspecified</pose>" << std::endl;
file << "\t\t<truncated>0</truncated>" << std::endl;
file << "\t\t<difficult>0</difficult>" << std::endl;
file << "\t\t<bndbox>" << std::endl;
file << "\t\t\t<xmin>" << rect.x << "</xmin>" << std::endl;
file << "\t\t\t<ymin>" << rect.y << "</ymin>" << std::endl;
file << "\t\t\t<xmax>" << rect.w << "</xmax>" << std::endl;
file << "\t\t\t<ymax>" << rect.h << "</ymax>" << std::endl;
file << "\t\t</bndbox>" << std::endl;
file << "\t</object>" << std::endl;
}
// 将所有矩形框信息写入XML文件
void writeXML(const std::string& filename, const std::string& folder, const std::string& imageFileName, const std::vector<cv::Rect>& rectangles) {
std::ofstream file;
file.open(filename, std::ios::app);
file << "<annotation>" << std::endl;
file << "\t<folder>" << folder << "</folder>" << std::endl;
file << "\t<filename>" << imageFileName << "</filename>" << std::endl;
file << "\t<source>" << std::endl;
file << "\t\t<database>Unknown</database>" << std::endl;
file << "\t</source>" << std::endl;
file << "\t<size>" << std::endl;
file << "\t\t<width>0</width>" << std::endl;
file << "\t\t<height>0</height>" << std::endl;
file << "\t\t<depth>3</depth>" << std::endl;
file << "\t</size>" << std::endl;
file << "\t<segmented>0</segmented>" << std::endl;
// 将所有OpenCV矩形框转换为自定义的矩形框结构体
std::vector<Rectangle> customRectangles;
for (const cv::Rect& rect : rectangles) {
customRectangles.push_back({ rect.x, rect.y, rect.width, rect.height });
}
// 写入所有矩形框信息
for (const Rectangle& rect : customRectangles) {
writeRectangle(file, rect);
}
file << "</annotation>" << std::endl;
file.close();
}
均值滤波差分->二值化->连通域->计算轮廓面积->返回坐标
int main(int argc, char** argv)
{
Mat dst = imread("..\\img\\test.jpg");
if (dst.empty()) {
printf("could not load iamge...\n");
return -1;
}
string filename = "annotation.xml";
string folder = "images";
string imageFileName = "test.jpg";
//均值滤波做差分
Mat dst_blur, diff, binary, dst_gray;
cvtColor(dst, dst_gray, COLOR_RGB2GRAY);
blur(dst_gray, dst_blur, Size(3, 501), Point(-1, -1));
absdiff(dst_gray, dst_blur, diff);
//imshow("差分", diff);
threshold(diff, binary, 70, 255, THRESH_BINARY);
// adaptiveThreshold(diff, binary, 255, THRESH_BINARY, ADAPTIVE_THRESH_GAUSSIAN_C, 7, 8);
medianBlur(binary, binary, 3);
namedWindow("二值化", WINDOW_NORMAL | WINDOW_KEEPRATIO);
imshow("二值化", binary);
std::vector<std::vector<cv::Point>>contours;
std::vector<cv::Rect> rectangles;
findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());
for (int i = 0; i < contours.size(); i++)
{
int aero = contourArea(contours[i]); //计算轮廓面积
if (aero > 200)
{
Rect rect = boundingRect(contours[i]);
std::vector<cv::Rect> rectangles;
rectangles.push_back({ rect.tl().x, rect.tl().y, rect.br().x, rect.br().y });
//绘制轮廓
//rect.tl().x, rect.tl().y, rect.br().x, rect.br().y
// drawContours(dst, contours, i, Scalar(0, 0, 255), 2); // polygon
rectangle(dst, rect, Scalar(0, 0, 255), 2); // 矩形框
cout << "左上顶点的坐标:" << rect.tl() << "右下顶点的坐标: " << rect.br() << endl;
writeXML(filename, folder, imageFileName, rectangles);
}
}
namedWindow("close", WINDOW_NORMAL | WINDOW_KEEPRATIO);
imshow("close", dst);
waitKey(0);
//imwrite("./result.jpg", dst);
return 0;
}
完整代码
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <fstream>
#include <vector>
using namespace cv;
using namespace std;
// 定义一个表示矩形框的结构体
struct Rectangle {
int x, y, w, h;
};
// 将一个矩形框信息写入XML文件
void writeRectangle(std::ofstream& file, const Rectangle& rect) {
file << "\t<object>" << std::endl;
file << "\t\t<name>rectangle</name>" << std::endl;
file << "\t\t<pose>Unspecified</pose>" << std::endl;
file << "\t\t<truncated>0</truncated>" << std::endl;
file << "\t\t<difficult>0</difficult>" << std::endl;
file << "\t\t<bndbox>" << std::endl;
file << "\t\t\t<xmin>" << rect.x << "</xmin>" << std::endl;
file << "\t\t\t<ymin>" << rect.y << "</ymin>" << std::endl;
file << "\t\t\t<xmax>" << rect.w << "</xmax>" << std::endl;
file << "\t\t\t<ymax>" << rect.h << "</ymax>" << std::endl;
file << "\t\t</bndbox>" << std::endl;
file << "\t</object>" << std::endl;
}
// 将所有矩形框信息写入XML文件
void writeXML(const std::string& filename, const std::string& folder, const std::string& imageFileName, const std::vector<cv::Rect>& rectangles) {
std::ofstream file;
file.open(filename, std::ios::app);
file << "<annotation>" << std::endl;
file << "\t<folder>" << folder << "</folder>" << std::endl;
file << "\t<filename>" << imageFileName << "</filename>" << std::endl;
file << "\t<source>" << std::endl;
file << "\t\t<database>Unknown</database>" << std::endl;
file << "\t</source>" << std::endl;
file << "\t<size>" << std::endl;
file << "\t\t<width>0</width>" << std::endl;
file << "\t\t<height>0</height>" << std::endl;
file << "\t\t<depth>3</depth>" << std::endl;
file << "\t</size>" << std::endl;
file << "\t<segmented>0</segmented>" << std::endl;
// 将所有OpenCV矩形框转换为自定义的矩形框结构体
std::vector<Rectangle> customRectangles;
for (const cv::Rect& rect : rectangles) {
customRectangles.push_back({ rect.x, rect.y, rect.width, rect.height });
}
// 写入所有矩形框信息
for (const Rectangle& rect : customRectangles) {
writeRectangle(file, rect);
}
file << "</annotation>" << std::endl;
file.close();
}
int main(int argc, char** argv)
{
Mat dst = imread("..\\img\\test.jpg");
if (dst.empty()) {
printf("could not load iamge...\n");
return -1;
}
string filename = "annotation.xml";
string folder = "images";
string imageFileName = "test.jpg";
//均值滤波做差分
Mat dst_blur, diff, binary, dst_gray;
cvtColor(dst, dst_gray, COLOR_RGB2GRAY);
blur(dst_gray, dst_blur, Size(3, 501), Point(-1, -1));
absdiff(dst_gray, dst_blur, diff);
//imshow("差分", diff);
threshold(diff, binary, 70, 255, THRESH_BINARY);
// adaptiveThreshold(diff, binary, 255, THRESH_BINARY, ADAPTIVE_THRESH_GAUSSIAN_C, 7, 8);
medianBlur(binary, binary, 3);
namedWindow("二值化", WINDOW_NORMAL | WINDOW_KEEPRATIO);
imshow("二值化", binary);
std::vector<std::vector<cv::Point>>contours;
std::vector<cv::Rect> rectangles;
findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE, cv::Point());
for (int i = 0; i < contours.size(); i++)
{
int aero = contourArea(contours[i]); //计算轮廓面积
if (aero > 200)
{
Rect rect = boundingRect(contours[i]);
std::vector<cv::Rect> rectangles;
rectangles.push_back({ rect.tl().x, rect.tl().y, rect.br().x, rect.br().y });
//绘制轮廓
//rect.tl().x, rect.tl().y, rect.br().x, rect.br().y
// drawContours(dst, contours, i, Scalar(0, 0, 255), 2); // polygon
rectangle(dst, rect, Scalar(0, 0, 255), 2); // 矩形框
cout << "左上顶点的坐标:" << rect.tl() << "右下顶点的坐标: " << rect.br() << endl;
writeXML(filename, folder, imageFileName, rectangles);
}
}
namedWindow("close", WINDOW_NORMAL | WINDOW_KEEPRATIO);
imshow("close", dst);
waitKey(0);
//imwrite("./result.jpg", dst);
return 0;
}
更多推荐
已为社区贡献1条内容
所有评论(0)