1.图片预处理,提取边界
经过处理后的图片轮廓更加清晰。更有利于后续的操作。
2.findContours()查找轮廓,drawContours()画出轮廓
3.contourArea()计算每个轮廓的面积,通过if(area>2000)筛选出图形后再画出轮廓
通过面积大小,将噪声过滤
下面见代码示例:
#include
#include
using namespace std;
using namespace cv;
void getContours(Mat imgDil, Mat img)
{
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
//找轮廓
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);//-1画出所有轮廓
vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
string objectType;
for (int i = 0; i < contours.size(); i++)
{
//取出每个轮廓的面积
int area = contourArea(contours[i]);
cout << area << endl;
//过滤小面积
if (area > 2000)
{
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02*peri, true);
//画出轮廓
drawContours(img, conPoly, i, Scalar(255, 0, 255), 3);
cout << conPoly[i].size() << endl;
boundRect[i] = boundingRect(conPoly[i]);
rectangle(img, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 3);
int objCor = (int)conPoly[i].size();
if (objCor == 3)
{
objectType = "Tri";
}
else if (objCor == 4)
{
float aspRatio = (float)boundRect[i].width / (float)boundRect[i].height;
if (aspRatio > 0.95 && aspRatio < 1.05)
{
objectType = "Square";
}
else
{
objectType = "Rect";
}
cout << aspRatio << endl;
}
else if (objCor > 4)
{
objectType = "Circle";
}
putText(img, objectType, { boundRect[i].x,boundRect[i].y - 5 }, FONT_HERSHEY_DUPLEX, 0.7, Scalar(0, 69, 255), 1);
}
}
}
int main()
{
Mat img = imread("D:\\photogallery\\其他\\颜色卡.jpg");
Mat imgGray, imgBlur,imgCanny,imgDil;
//图片预处理
resize(img, img, Size(), 0.8, 0.8);
cvtColor(img, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, imgBlur, Size(3, 3), 0, 0);
Canny(imgBlur, imgCanny, 25, 75);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(imgCanny, imgDil, kernel);
getContours(imgDil,img);
imshow("img", img);
imshow("imggray", imgGray);
imshow("imgblur", imgBlur);
imshow("imgcanny", imgCanny);
imshow("imgdil", imgDil);
waitKey(0);
return 0;
}