使用opencv提取一副图像中的圆环区域

任务简述

今天使用opencv 做了一个计算机视觉任务:
源图像如下
使用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掩码
  • 熟悉斑点检测算子,可以看以下博文: