简介:刚开始学习OpenCV的时候,老师布置了一个Qt+OpenCV来识别物体形状的任务。识别的形状主要有矩形、五角星、圆形。
这个是我们要处理的图片
思路:首先将图片进行一系列的预处理,然后进行轮廓检测,通过轮廓检测来获取每个物体的轮廓面积(即物体面积)设为S1。其次,我们获取每个轮廓对应的最小外接矩形面积S2。最后,我们求取最小外接据徐面积与轮廓面积的比值R。我们通过比值R来判断该物体为什么形状。如矩形的最小外接矩形就是其本身,使用R=1。
下面是具体代码:
String image_path = "C:\\Users\\86195\\Pictures\\testimg\\*.jpg"; //图片路径
Mat img,hsv,cloneImg;
int num_star = 0;int num_white = 0; int num_black = 0;int num_rect= 0;
img = imread(image_path);
cloneImg =img.clone();
cv::resize(img,img,Size(480,640));
cv::resize(cloneImg,cloneImg,Size(480,640));
cvtColor(img,hsv,COLOR_BGR2HSV);
imshow("hsv", hsv);
vector<Mat> channels;
split(hsv, channels);//分离HSV
imshow("channels",channels[2]);
Canny(channels[2],channels[2],3000,600,5);
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
// 轮廓检测
findContours(channels[2], contours, hierachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(-1,-1));
vector<RotatedRect> box(contours.size());
for (size_t i = 0;i<contours.size();i++) // 遍历获取到的轮廓
{
double area_contour = contourArea(contours[i]); // 获取该轮廓的面积
if(area_contour > 1000 && area_contour<20000) //因为图片处理原因,难免会有一些干扰因素,所有我们可以使用比较轮廓面积的方法排除一些我们不需要的轮廓或杂质
{ // 获取轮廓的最小外接矩形并求出该轮廓与其最小外接矩形的比例
box[i] = minAreaRect(Mat(contours[i]));
double area_minrect = box[i].size.area();
double result = area_contour/area_minrect;
if( result>0.9) // 矩形的轮廓面积与其最小外接矩形的面积相等,考虑到操作误差,所有我们将比例大于0.9的认为是矩形
{
qDebug() <<"该物体形状为矩形"<<endl;
num_rect++;
}
if(result<0.9 && result>0.75) //圆形
{
// 如果我们想要区分物体是什么颜色的,我们可以去其一点,通过该点的rgb来判断为什么颜色
// 这里我们去圆心的像素进行判断
int x = box[i].center.x;
int y = box[i].center.y;
Vec3b intensity =img.at<Vec3b>(y, x);//读一个RGB像素点的像素值
int pixel = intensity.val[0]; /*通道0*/
if (pixel < 150) //我们认为通道0像素小于150的为黑色,否则为白色
{
qDebug() <<"黑圆形"<<endl;
num_black++;
}
else
{
qDebug() <<"白圆形"<<endl;
num_white++;
}
}
if(result>0.3 && result<0.75) //五角星
{
num_star++;
}
drawContours(cloneImg, contours, i, Scalar(0, 255, 0), 3, 8, hierachy); //画出轮廓
}
}
qDebug() <<" 白色棋子个数:" <<num_white <<"\n" <<"黑色棋子个数:" <<num_black <<"\n"<<"矩形个数:"<<num_rect<<"\n"<<"五角星个数:"<<num_star;
qDebug() <<"\n";
这个是效果图: