使用opencv提取一副图像中的圆环区域
任务简述
今天使用opencv 做了一个计算机视觉任务:
源图像如下
检测的目标为红框圈选的白色点
思路简述
首先是提取出这两个白色小点在的圆环,然后在此圆环之中使用阈值函数就可以看到提取出来的噪声点。如果要在源图像之中标注出来噪声点的话需要使用斑点检测算子。
源程序
void process(){
Mat source = imread(""); //从磁盘之中读取图片
Mat circleROI; //定义圆环ROI
Mat roi1, roi2, roi;
//三个变量都按照source的尺寸初始化为零,
roi1 = Mat::zeros(mat.size(), CV_8UC1);
roi2 = Mat::zeros(mat.size(), CV_8UC1);
roi = Mat::zeros(mat.size(), CV_8UC1);
//在源图像之中画圆,圆的位置和尺寸是手工计算出来的
//circle()函数的最后一个参数-1表示为区域都填充为RGB(255, 255, 255)
circle(roi1, Point(1570, 1105), 610, CV_RGB(255, 255, 255), -1);
circle(roi2, Point(1570, 1105), 500, CV_RGB(255, 255, 255), -1);
//大圆减去小圆就是提出出来的圆环
cv::subtract(roi1, roi2, roi);
//把圆环区域的图像复制出来,进行下一步操作,
//其实这里照理来说可以在后续操作之中直接将roi作为掩码使用
//但是我不知道哪里出问题了,会报异常,因此这样直接复制处理
mat.copyTo(ROI_circle, roi);
//二值化处理就可以看到两个白色小点的位置
Mat result;
threshold(ROI_circle, result, 128, 255, CV_THRESH_BINARY);
//显示
imshow("result", result);
}
以上程序是使用二值化,直接显示目标。并没有计算出图像的位置信息。
void process(){
Mat source = imread(""); //从磁盘之中读取图片
Mat circleROI; //定义圆环ROI
Mat roi1, roi2, roi;
//三个变量都按照source的尺寸初始化为零,
roi1 = Mat::zeros(mat.size(), CV_8UC1);
roi2 = Mat::zeros(mat.size(), CV_8UC1);
roi = Mat::zeros(mat.size(), CV_8UC1);
//在源图像之中画圆,圆的位置和尺寸是手工计算出来的
//circle()函数的最后一个参数-1表示为区域都填充为RGB(255, 255, 255)
circle(roi1, Point(1570, 1105), 610, CV_RGB(255, 255, 255), -1);
circle(roi2, Point(1570, 1105), 500, CV_RGB(255, 255, 255), -1);
//大圆减去小圆就是提出出来的圆环
cv::subtract(roi1, roi2, roi);
//把圆环区域的图像复制出来,进行下一步操作,
//其实这里照理来说可以在后续操作之中直接将roi作为掩码使用
//但是我不知道哪里出问题了,会报异常,因此这样直接复制处理
mat.copyTo(ROI_circle, roi);
//二值化处理就可以看到两个白色小点的位置
//使用opencv自带的斑点检测算子
SimpleBlobDetector::Params params;
params.minDistBetweenBlobs = 0.0f;
params.filterByInertia = false;
params.filterByConvexity = false;
params.filterByColor = false;
params.filterByCircularity = false;
params.filterByArea = false;
// 声明根据圆度过滤,设置最大与最小圆度
//圆度越高,检测到的圆越规则
params.filterByCircularity = true;
params.minCircularity = 0.4;
params.maxCircularity = 1.0;
//// 凸包形状分析 - 过滤凹包
//params.filterByConvexity = true;
//params.minConvexity = 0.2
//params.minConvexity = 1.0;
//斑点面积大小
params.filterByArea = true;
params.minArea = 20;
params.maxArea = 300;
////阈值
//params.minThreshold = 160;
//params.maxThreshold = 255;
//params.thresholdStep = 30;
SimpleBlobDetector detector(params);
detector.create("SimpleBlob");
//检测到的斑点
vector<KeyPoint> keypoints;
detector.detect(ROI_circle, keypoints);
std::cout << keypoints.size() << std::endl;
Mat img_with_keypoints;
//在 mat 图像画上keypoint 并保存在img_with_keyPoint之中,
drawKeypoints(mat, keypoints, img_with_keypoints, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//显示
imshow("img_with_keypoints", result);
}
总结
- 图形的ROI的使用其实是一个很常用的思想,因为对于图像来说,我们可以先提取一部分区域,再在此区域上进一步处理。
关于ROI可以看以下博文:
【OpenCV学习笔记】十三、ROI与mask掩码 - 熟悉斑点检测算子,可以看以下博文: