void test_contours_feature()
{
cv::Mat src;
src = cv::imread("feature.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "Cannot load image" << endl;
return;
}
cv::imshow("src", src);
cv::Mat binary;
cv::threshold(src, binary, 150, 255, cv::THRESH_BINARY_INV);
cv::Mat k55 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(-1, -1));
cv::morphologyEx(binary, binary, cv::MORPH_OPEN, k55, cv::Point(-1, -1), 1);
cv::namedWindow("binary",cv::WINDOW_NORMAL);
cv::imshow("binary", binary);
std::vector > defectContours;
std::vector hierarchyDefect;
cv::findContours(binary, defectContours, hierarchyDefect, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
cv::Mat contours = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawCenterPos = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawHull = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawRotateRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawMinEnclosingCircle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawMinEnclosingTriangle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Mat drawEllipse = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
std::vector> PolyDPs;
cv::Mat drawPolyDP = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
std::vector > hull(defectContours.size());
for (int i = 0; i < defectContours.size(); i++)
{
//轮廓 白色
cv::drawContours(contours, defectContours, i, cv::Scalar(255,255,255), 1);
//求面积
double fArea = cv::contourArea(defectContours[i]);
qDebug()< boxPts(4);
rotateRect.points(boxPts.data());
for (int j = 0; j < 4; j++)
{
cv::line(drawRotateRect, boxPts[j], boxPts[(j + 1) % 4], cv::Scalar(128, 128, 0), 1, 8); //绘制最小外接矩形每条边
}
//最小外接圆 棕褐色
cv::Point2f center;
float fRadius = 0;
cv::minEnclosingCircle(defectContours[i], center, fRadius);
cv::circle(drawMinEnclosingCircle, center, fRadius, cv::Scalar(140,180,210),1);
//最小外界三角形 粉色
std::vector points;
cv::minEnclosingTriangle(defectContours[i], points);
cv::line(drawMinEnclosingTriangle, points[0], points[1], cv::Scalar(193, 182, 255), 1, 8); //绘制最小外接三角形每条边
cv::line(drawMinEnclosingTriangle, points[2], points[1], cv::Scalar(193, 182, 255), 1, 8); //绘制最小外接三角形每条边
cv::line(drawMinEnclosingTriangle, points[2], points[0], cv::Scalar(193, 182, 255), 1, 8); //绘制最小外接三角形每条边
//椭圆 紫罗兰色
cv::RotatedRect ellipse = cv::fitEllipse(defectContours[i]);
cv::ellipse(drawEllipse, ellipse, cv::Scalar(226,43,138));
//多边形逼近 洋红色
std::vector PolyDP;
//cv::Mat PolyDP ;
cv::approxPolyDP(defectContours[i],PolyDP, 0.5, true);
PolyDPs.push_back(PolyDP);
//cv::drawContours(drawPolyDP, PolyDP, 0, cv::Scalar(23,56,234));
//drawPolyDP += cv::Mat(PolyDP);
}
//画多边形逼近
for(int j = 0; j < PolyDPs.size(); j++)
{
cv::drawContours(drawPolyDP, PolyDPs, j, cv::Scalar(255,0,255),1);
}
drawCenterPos += contours;
drawRect += contours;
drawHull += contours;
drawRotateRect += contours;
drawMinEnclosingCircle += contours;
drawMinEnclosingTriangle += contours;
drawEllipse += contours;
cv::namedWindow("contours",cv::WINDOW_NORMAL);
cv::imshow("contours", contours);
cv::namedWindow("drawRect",cv::WINDOW_NORMAL);
cv::imshow("drawRect", drawRect);
cv::namedWindow("drawHull",cv::WINDOW_NORMAL);
cv::imshow("drawHull", drawHull);
cv::namedWindow("drawRotateRect",cv::WINDOW_NORMAL);
cv::imshow("drawRotateRect", drawRotateRect);
cv::namedWindow("drawCenterPos",cv::WINDOW_NORMAL);
cv::imshow("drawCenterPos", drawCenterPos);
cv::namedWindow("drawMinEnclosingCircle",cv::WINDOW_NORMAL);
cv::imshow("drawMinEnclosingCircle", drawMinEnclosingCircle);
cv::namedWindow("drawMinEnclosingTriangle",cv::WINDOW_NORMAL);
cv::imshow("drawMinEnclosingTriangle", drawMinEnclosingTriangle);
cv::namedWindow("drawEllipse",cv::WINDOW_NORMAL);
cv::imshow("drawEllipse", drawEllipse);
cv::namedWindow("drawPolyDP",cv::WINDOW_NORMAL);
cv::imshow("drawPolyDP", drawPolyDP);
}
#include
#include
using namespace cv;
using namespace std;
Mat imgGray, imgBlur, imgCanny, imgDil, imgErode;
//定义一个轮廓处理函数
void getContours(Mat imgDil,Mat img) {
vector> contours;//{ {Point(20,30),Point(50,60)},{}, {}}
vectorhierarchy;//vector里放置了四个int类型的变量
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
vector>conPoly(contours.size());
vector boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
cout << area << endl;//需要正确过滤的面积(过滤噪点)
string objectType;
//判断形状
if (area>1000)
{
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);//找到近似值
cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(conPoly[i]);//边界矩形
int objCor = (int)conPoly[i].size();
if (objCor == 3) { objectType = "Tri"; }
if (objCor == 4) {
float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;
cout << aspRatio << endl;
if (aspRatio > 0.95 && aspRatio < 1.05) { objectType = "Square"; }
else { objectType = "Rect";
}
}
if (objCor > 4) { objectType = "Circle"; }
drawContours(img, conPoly, i, Scalar(255, 0, 255), 2);//描绘计数轮廓
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);//绘制边界矩形
//打印图形的名字
putText(img, objectType, { boundRect[i].x,boundRect[i].y - 5 }, FONT_HERSHEY_PLAIN, 1, Scalar(0, 69, 255), 2);
}
}
}
void main() {
string path = "temp.png";
Mat img = imread(path);
//图像的预处理
//1.将照片转换为灰度
cvtColor(img, imgGray, COLOR_BGR2GRAY);
//2.高斯模糊
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
//3.Canny边缘检测器
Canny(imgBlur, imgCanny, 25, 75);
//4.创建一个可以使用膨胀的内核
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
//5.图像膨胀
dilate(imgCanny, imgDil, kernel);
getContours(imgDil,img);
imshow("Image", img);
waitKey(0);
}