案例场景
将图片中的某个元素,提取。这里在黑白图中扣取圆圈部分
实现方法
代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
#define PIC_PATH "/work/opencv_pic/"
#define PIC_NAME "case3.png"
int main(void)
{
Mat src,gray_src;
//获取完整的图片路径及名称
string pic = string(PIC_PATH)+string(PIC_NAME);
//打印图片路径
cout << "pic path is :"<<pic<<endl;
//读取图片
src = imread(pic);
//判断图片是否存在
if(src.empty())
{
cout<<"pic is not exist!!!!"<<endl;
return -1;
}
imshow("原图显示",src);
cvtColor(src,gray_src,COLOR_BGR2GRAY);
//图像二值化
threshold(gray_src,gray_src,0,255,THRESH_BINARY | THRESH_OTSU);
//形态学开闭操作 去除噪点、不连续区域等干扰信息 方便以后特征提取
Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
//闭操作 消除小黑点 使某些不连续区域连续起来
morphologyEx(gray_src,gray_src,MORPH_CLOSE,kernel,Point(-1,-1));
//开操作 消除小白点 使某些白色噪点消失 画面更纯净
morphologyEx(gray_src,gray_src,MORPH_OPEN,kernel,Point(-1,-1));
//获得纯净的 分区明显的特征图
imshow("形态学处理",gray_src);
//轮廓查找
vector<vector<Point>> contours; //轮廓集合
vector<Vec4i> hierarchy; //轮廓索引关系
findContours(gray_src,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
//轮廓绘制
Mat contourimg = Mat::zeros(src.size(),CV_8UC3);
Mat circleimg = src.clone();
for(size_t i=0;i<contours.size();i++)
{
//如果有干扰轮廓出现 通过面积过滤 过滤面积较小的轮廓(这里我们的目标轮廓是比较大的)
double area = contourArea(contours[i]);
if(area < 50)
continue;
//通过横纵比滤除干扰轮廓 检测的目标圆接近1:1
Rect rect = boundingRect(contours[i]);
float width = rect.width;
float hight = rect.height;
float calc_val = width/hight;
if(calc_val > 0.9 && calc_val <1.1)
{
drawContours(contourimg,contours,i,Scalar(0,0,255),2,8,Mat(),0,Point());
imshow("筛选后轮廓绘制",contourimg);
//计算圆心位置
int x = rect.x + rect.width /2;
int y = rect.y + rect.height /2;
Point cc = Point(x,y);
//计算半径
double r = arcLength(contours[i],true)/(2*CV_PI);
cout << "半径" << r << endl;
//绘制圆形
circle(circleimg ,cc,cvRound(r),Scalar(0,0,255),2,8,0);
imshow("原图目标标定",circleimg);
}
}
waitKey(0);
destroyAllWindows();
return 0;
}