红色的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;
}