opencv转HSV再找红色圆——霍夫圆检测

在这里插入图片描述

在这里插入图片描述

红色的H范围大概是(0~8)∪(160,180) S是饱和度,一般是大于一个值,S过低就是灰色(参考值S>80), V是亮度,过低就是黑色,过高就是白色(参考值220>V>50)。判断区域颜色是否相同,可以直接比较这两个区域像素的HSV值。如果要完全相同,则各像素点的H,S,V的值都要一样,否则可以有一定误差范围(具体是多少就只能自己估计了)。

/*****************************************************************************************
1、五子棋棋盘棋子识别检测

2021.2.25:开始,初版,找到了棋盘边缘图像

*****************************************************************************************/
#include<opencv2/opencv.hpp>
#include <iostream> 
#include <fstream>  
#include <stdlib.h> //srand()和rand()函数 
#include <time.h> //time()函数 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/objdetect/objdetect.hpp> 
#include <opencv2/ml/ml.hpp>  
#include<opencv2\opencv.hpp>
#include <opencv2\imgproc\types_c.h>
#include<windows.h>
using namespace std;
using namespace cv;
using namespace ml;

#define PI 3.1415926
#define  ROTATED_SIZE   600 //透视变换后的表盘图像大小
#define  CUT_SIZE       0 //透视变换时四周裁剪长度

#define  debug_show_picture        1 //是否显示部分调试图片,方便调试
/*打印等级,修改后面的宏定义可以改变函数输出打印等级*/
#define ALG_PRTINT_LEVER PRINT_LEVEL_UNLIMIT


#define ALG_PRTINT(...)  SAL_printf(__VA_ARGS__)
#define ALG_PRT(...)     ALG_PRTINT(__FUNCTION__, __LINE__, PRINT_LEVEL_UNLIMIT, __VA_ARGS__)
#define ALG_DBG(...)     ALG_PRTINT(__FUNCTION__, __LINE__, PRINT_LEVEL_DBG,     __VA_ARGS__)
#define ALG_WAR(...)     ALG_PRTINT(__FUNCTION__, __LINE__, PRINT_LEVEL_WRN,     __VA_ARGS__)
#define ALG_ERR(...)     ALG_PRTINT(__FUNCTION__, __LINE__, PRINT_LEVEL_ERR,     __VA_ARGS__)

/***********************************************************************************************
* @enum     HAT_SAL_PRT_LEVEL_E
* @brief    打印输出的等级
***************************************************************************************************/
typedef enum _PRT_LEVEL_E_
{
    
    
	PRINT_LEVEL_ERR = 0,        /*错误打印信息*/
	PRINT_LEVEL_WRN = 1,        /*警告打印信息*/
	PRINT_LEVEL_DBG = 2,         /*调试打印信息*/
	PRINT_LEVEL_UNLIMIT = 3,    /*无限制打印信息*/
	PRINT_LEVEL_NOPRT = 4,      /*没有打印信息*/
} PRT_LEVEL_E;

/*******************************************************************************
Function:	SAL_printf
Description: 该函数能够通过设置的打印等级ALG_PRTINT_LEVER,来控制是否输出相关语句
Input:
Output:
Return:
0:			Successful
ohters:		Failed
*******************************************************************************/
void SAL_printf(const char *pFun, UINT line, PRT_LEVEL_E levelParam, const char *fmt, ...)
{
    
    
	static INT8 g_printfInfo[4][16] = {
    
     "ERR", "WAR", "DBG", "INF" };
	va_list p;
	if (ALG_PRTINT_LEVER == PRINT_LEVEL_NOPRT || levelParam == PRINT_LEVEL_NOPRT)
	{
    
    
		return;
	}
	if (levelParam <= ALG_PRTINT_LEVER)
	{
    
    
		va_start(p, fmt);
		printf("[DIYUN_ALG][%s][%s][%4d] ", g_printfInfo[levelParam], pFun, line);
		vprintf(fmt, p);
		va_end(p);
	}
}



//RGB转HSV
void RGB2HSV(double red, double green, double blue, double& hue, double& saturation, double& intensity)
{
    
    

	double r, g, b;
	double h, s, i;

	double sum;
	double minRGB, maxRGB;
	double theta;

	r = red / 255.0;
	g = green / 255.0;
	b = blue / 255.0;

	minRGB = ((r<g) ? (r) : (g));
	minRGB = (minRGB<b) ? (minRGB) : (b);

	maxRGB = ((r>g) ? (r) : (g));
	maxRGB = (maxRGB>b) ? (maxRGB) : (b);

	sum = r + g + b;
	i = sum / 3.0;

	if (i<0.001 || maxRGB - minRGB<0.001)
	{
    
    
		h = 0.0;
		s = 0.0;
	}
	else
	{
    
    
		s = 1.0 - 3.0*minRGB / sum;
		theta = sqrt((r - g)*(r - g) + (r - b)*(g - b));
		theta = acos((r - g + r - b)*0.5 / theta);
		if (b <= g)
			h = theta;
		else
			h = 2 * 3.1415926 - theta;
		if (s <= 0.01)
			h = 0;
	}

	hue = (int)(h * 180 / 3.1415926);
	saturation = (int)(s * 100);
	intensity = (int)(i * 100);
}


int main()
{
    
    

	float ret = 0;
	float final_value = 0;
	float min_value = 0;/*最新刻度值*/
	float max_value = 450;/*最大刻度值*/
	float Min_scale_value = 10;/*最小格单位*/
	Mat srcImage0 = imread("1.jpg");//读取图片 
	int begin, duration;
	begin = clock();											   //Mat srcImage0 = imread("app/1.jpg");//读取图片 
	if (srcImage0.empty())
	{
    
    
		cout << " 待预测图像不存在: " << endl;
		printf("[ALG ERROR][函数:%s][行号:%d],图片未正常读取,请检查输入路径十分正确 \n", __FUNCTION__, __LINE__, 1);
		cout << " 待预测图像不存在: " << endl;
	}
	Mat srcImage;
	resize(srcImage0, srcImage0, Size(960,540));
	//cvtColor(srcImage0, srcImage, CV_BGR2GRAY);
	//srcImage = srcImage>150; // 二值化
	//imshow("二值化", srcImage);

	Mat image_copy_C3;   //clone函数创建新的图片 彩色

	image_copy_C3 = srcImage0.clone();   //clone函数创建新的图片 


	int x, y;
	double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
	int width1 = image_copy_C3.cols * 3;
	int height1 = image_copy_C3.rows;
	for (x = 0; x < height1; x++)
	{
    
    
		uchar* data = image_copy_C3.ptr<uchar>(x);//获取第i行的首地址
		for (y = 0; y < width1; y += 3)
		{
    
    
			B = data[y];
			G = data[y + 1];
			R = data[y + 2];
			RGB2HSV(R, G, B, H, S, V);
			//红色范围,范围参考的网上。可以自己调
			//	if ((H >= 270 && H <= 360 || H >= 0 && H <= 20) && (S >= 20 && S <= 360) && (V>0 && V < 220))无人机比较好的
			if ((H >= 270 && H <= 360 || H >= 0 && H <= 20) && (S >= 15 && S <= 360) && (V>0 && V < 360))
				data[y] = data[y + 1] = data[y + 2] = 255;
			else data[y] = data[y + 1] = data[y + 2] = 0;
		}
	}
	Mat vec_rgb;
	cvtColor(image_copy_C3, vec_rgb, CV_BGR2GRAY);//灰度化
												  //【3】srcImage取大于阈值119的那部分
	vec_rgb = vec_rgb > 120;
	namedWindow("hsv空间图像", 0);
	imshow("hsv空间图像", vec_rgb);
	waitKey(1);

	/****2、圆形检测   *******************************************************/
	//      第五个参数   圆的圆心之间的最小距离
	vector<Vec3f> circles;
	//第二个参数:累加器阈值
	//
	HoughCircles(vec_rgb, circles, CV_HOUGH_GRADIENT, 1.5, 200, 150, 70, 10, 388);

	//【5】依次在图中绘制出圆  
	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]);
		cout << "圆心  " << i << "= " << center << ";\n" << endl;
		cout << "半径= " << i << "= " << radius << ";\n" << endl;

		//绘制圆心  
		circle(srcImage0, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		//绘制圆轮廓  
		circle(srcImage0, center, radius, Scalar(155, 50, 255), 3, 8, 0);
		//绘制圆心  
		circle(srcImage0, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		//绘制圆轮廓  
		circle(srcImage0, center, radius, Scalar(155, 50, 255), 3, 8, 0);
	}
	cout << "共检测到圆" << circles.size() << " 个圆" << ";\n" << endl;

	//【6】显示效果图    
	duration = clock() - begin;
	ALG_ERR("圆形识别用时约: %d毫秒 \n", duration * 1000 / CLOCKS_PER_SEC);

	namedWindow("【彩色效果图】", 0);//参数为零,则可以自由拖动
	imshow("【彩色效果图】", srcImage0);

	while (1)
	{
    
    
		ALG_ERR("程序运行结束,请查收\n");
	}
	return 0;


}

猜你喜欢

转载自blog.csdn.net/mao_hui_fei/article/details/114650951