Extract the circle in the image

Idea: Process the three RGB channels of the image separately, extract the black, then use Gaussian filtering to filter out the black shadows, and finally use Hough to detect the circle

// https://blog.csdn.net/piaoxuezhong/article/details/60757278?utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-1.nonecase
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<opencv2/opencv.hpp>
#include<vector>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<cassert>

using namespace cv;
using namespace std;

int main()
{
    
    
	Mat srcImage = imread("31.jpg");
	Mat midImage, dstImage;
	namedWindow("原图", WINDOW_NORMAL);
	imshow("原图", srcImage);

	Mat BinRGBImg = srcImage.clone();	//用双重循环给此MAT赋值
	unsigned char pixelB, pixelG, pixelR;

	for (int i = 0; i < srcImage.rows; i++)   //通过颜色分量将图片进行二值化处理
	{
    
    
		for (int j = 0; j < srcImage.cols; j++)
		{
    
    
			pixelB = srcImage.at<Vec3b>(i, j)[0]; //获取图片各个通道的值
			pixelG = srcImage.at<Vec3b>(i, j)[1];
			pixelR = srcImage.at<Vec3b>(i, j)[2];

			// 用PS读取各像素点RGB通道值,可得知圆R、G、B范围
			if (pixelB<95 && pixelB>45 && pixelR<70 && pixelR>45)
			{
    
                                               //将各个通道的值和各个通道阈值进行比较
				BinRGBImg.at<Vec3b>(i, j)[0] = 255;     //符合颜色阈值范围内的设置成白色
				BinRGBImg.at<Vec3b>(i, j)[1] = 255;
				BinRGBImg.at<Vec3b>(i, j)[2] = 255;
			}
			else
			{
    
    
				BinRGBImg.at<Vec3b>(i, j)[0] = 0;        // 不符合颜色阈值范围内的设置为黑色
				BinRGBImg.at<Vec3b>(i, j)[1] = 0;
				BinRGBImg.at<Vec3b>(i, j)[2] = 0;
			}
		}
	}

	
	namedWindow("RGB通道处理后的图", WINDOW_NORMAL);
	imshow("RGB通道处理后的图", BinRGBImg);

	vector<Vec3f> circles;
	cvtColor(BinRGBImg, BinRGBImg, CV_BGR2GRAY);

	// 用高斯滤波滤去阴影部分的黑色,使得后续提取出来的圆为真正的圆
	GaussianBlur(BinRGBImg, BinRGBImg, cv::Size(9, 9), 3, 3);
	namedWindow("高斯滤波后", WINDOW_NORMAL);
	imshow("高斯滤波后", BinRGBImg);
	
	// BinRGBImg.rows/2为圆心之间的最小距离;40为检测圆的阈值,值越大检测出圆越难,但越精确
	 HoughCircles(BinRGBImg, circles, CV_HOUGH_GRADIENT, 1, BinRGBImg.rows / 2, 100, 40, 0, 0);
	 cout << "检测出圆的个数为" << circles.size() << endl;

	//依次在图中绘制出圆

	 
	 // 一般只能检测出一个圆,故这个for循环可以代替只输出一个圆
	for (size_t i = 0; i < circles.size(); i++)
	{
    
    
		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
		int radius = cvRound(circles[i][2]);
		//绘制圆心
		circle(BinRGBImg, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		//绘制圆轮廓
		circle(BinRGBImg, center, radius, Scalar(155, 50, 255), 3, 8, 0);
		cout << "圆心为:" << center << endl;
		cout << "半径为:" << radius << endl;
	}

	namedWindow("效果图", WINDOW_NORMAL);
	imshow("效果图", BinRGBImg);

	waitKey(0);
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44612221/article/details/108904833