opencv 圆形检测
上面是我最终输入和输出图片
#include
#include
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat img, img1, img2;
Mat img_resize, img1_resize, img2_resize;
Mat src = imread("right.bmp");
cout << src.channels() << endl;
cvtColor(src, img, CV_BGR2GRAY);
cout << img.channels() << endl;
resize(img, img_resize, Size(img.size().width0.5,img.size().height0.5));
namedWindow("原始图像left",1);
imshow("原始图像left", img_resize);
waitKey(0);
cv::GaussianBlur(img, img1, Size(5, 5), 0, 0);
resize(img1, img1_resize, Size(img.size().width0.5, img.size().height0.5));
namedWindow("高斯滤波图像",1);
imshow("高斯滤波图像", img1_resize);
waitKey(0);
Canny(img1, img2, 50, 150, 3);
resize(img2, img2_resize, Size(img.size().width0.5, img.size().height0.5));
namedWindow("canny图像");
imshow("canny图像", img2_resize);
waitKey(0);
morphologyEx(img2, img2, CV_MOP_CLOSE, NULL);
resize(img2, img2_resize, Size(img.size().width0.5, img.size().height0.5));
namedWindow("闭运算图像");
imshow("闭运算图像", img2_resize);
waitKey(0);
//找轮廓
vector< vector< cv::Point> > contours;
vector< cv::Vec4i > hierarchy;
findContours(img2, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
cout << "轮廓数为" << contours.size() << endl;
for (int i = 0; i < contours.size(); i++)
{
cout << i << "轮廓大小为" << contours[i].size() << endl;
}
//画轮廓
img2 = cv::Scalar::all(0);
drawContours(img2, contours,-1, cv::Scalar::all(255));//设置-1是全部轮廓都画出来,其余数值是第几个轮廓
resize(img2, img2_resize, Size(img.size().width0.5, img.size().height0.5));
imshow("Contours", img2_resize);
waitKey(0);
//去除过大或者过小轮廓
int cmin = 20; // minimum contour length
int cmax = 50; // maximum contour length
std::vector<std::vectorcv::Point>::const_iterator itc = contours.begin();
while (itc != contours.end()) {
if (itc->size() < cmin || itc->size() > cmax)
itc = contours.erase(itc);
else
++itc;
}
cout << "去除过大或者过小轮廓轮廓数为" << contours.size() << endl;
img2 = cv::Scalar::all(0);
drawContours(img2, contours, -1, cv::Scalar::all(255));//设置-1是全部轮廓都画出来,其余数值是第几个轮廓
resize(img2, img2_resize, Size(img.size().width0.5, img.size().height0.5));
imshow("去除过大和过小轮廓后Contours", img2_resize);
waitKey(0);
//周长和面积筛选
std::vector<std::vectorcv::Point>::const_iterator itc1 = contours.begin();
while (itc1 != contours.end()) {
if (abs(arcLength(*itc1, 1) - arcLength(itc1, 0))>3 || contourArea(itc1, 0) == contourArea(itc1, 1)(-1))//这个能筛选出闭合轮廓,还能去除一些很小的斑点
itc1= contours.erase(itc1);
else
++itc1;
}
cout << "筛选过后" << contours.size() << endl;
img2 = cv::Scalar::all(0);
drawContours(img2, contours, -1, cv::Scalar::all(255));//设置-1是全部轮廓都画出来,其余数值是第几个轮廓
resize(img2, img2_resize, Size(img.size().width0.5, img.size().height0.5));
imshow("周长筛选", img2_resize);
waitKey(0);
//椭圆拟合
Mat cimg = Mat::zeros(img2.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
//椭圆拟合
RotatedRect box = fitEllipse(contours[i]);
//如果长宽比大于30,则排除,不做拟合
if (MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height) * 2)
continue;
//画出追踪出的轮廓
drawContours(cimg, contours, (int)i, Scalar::all(255), 1, 8);
//画出拟合的椭圆
ellipse(cimg, box, Scalar(0, 0, 255), 1, CV_AA);
}
resize(cimg, cimg, Size(cimg.size().width0.5, cimg.size().height0.5));
imshow("拟合结果", cimg);
waitKey(0);
