前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用opencv识别图像红色区域,并输出红色区域中心点坐标

使用opencv识别图像红色区域,并输出红色区域中心点坐标

作者头像
砸漏
发布2020-11-02 10:24:09
2.8K0
发布2020-11-02 10:24:09
举报
文章被收录于专栏:恩蓝脚本

适用小白,大佬勿喷

个人配置:vs2013 ; opencv 3.0 ;

直接上效果图

注意:右下角的水印把中心点挡住了,要仔细看才能看到

下面是代码:

代码语言:javascript
复制
#include <iostream 
#include<opencv2\opencv.hpp 
#include <opencv2/imgproc/imgproc.hpp 
#include <opencv2/highgui/highgui.hpp 
#define PI 3.1415926
using namespace cv;
using namespace std;
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 * PI - theta;
if (s <= 0.01)
h = 0;
}
hue = (int)(h * 180 / PI);
saturation = (int)(s * 100);
intensity = (int)(i * 100);
}
Mat picture_red(Mat input)
{
Mat frame;
Mat srcImg = input;
frame = srcImg;
waitKey(1);
int width = srcImg.cols;
int height = srcImg.rows;
int x, y;
double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
Mat vec_rgb = Mat::zeros(srcImg.size(), CV_8UC1);
for (x = 0; x < height; x++)
{
for (y = 0; y < width; y++)
{
B = srcImg.at<Vec3b (x, y)[0];
G = srcImg.at<Vec3b (x, y)[1];
R = srcImg.at<Vec3b (x, y)[2];
RGB2HSV(R, G, B, H, S, V);
//红色范围,范围参考的网上。可以自己调
if ((H  = 312 && H <= 360) && (S  = 17 && S <= 100) && (V 18 && V < 100))
vec_rgb.at<uchar (x, y) = 255;
/*cout << H << "," << S << "," << V << endl;*/
}
}
/*imshow("hsv", vec_rgb);*/
return vec_rgb;
}
void O_x1y1(Mat in, double *x1, double *y1, double *x2, double *y2)
{
Mat matSrc = in;
/*Mat matSrc = imread("qwer9.png", 0);*/
GaussianBlur(matSrc, matSrc, Size(5, 5), 0);//高斯滤波,除噪点
vector<vector<Point    contours;//contours的类型,双重的vector
vector<Vec4i  hierarchy;//Vec4i是指每一个vector元素中有四个int型数据。
//阈值
threshold(matSrc, matSrc, 100, 255, THRESH_BINARY);//图像二值化
//寻找轮廓,这里注意,findContours的输入参数要求是二值图像,二值图像的来源大致有两种,第一种用threshold,第二种用canny
findContours(matSrc.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
/// 计算矩
vector<Moments  mu(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
/// 计算矩中心:
vector<Point2f  mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
/// 绘制轮廓
Mat drawing = Mat::zeros(matSrc.size(), CV_8UC1);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(255);
//drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());//绘制轮廓函数
circle(drawing, mc[i], 4, color, -1, 8, 0);
}
*x1 = mc[0].x;
*y1 = mc[0].y;
*x2 = mc[contours.size()-1].x;
*y2 = mc[contours.size() - 1].y;
imshow("outImage", drawing);
}
int main()
{
double xx1, yy1, xx2, yy2;
double x1, y1, x2, y2;
Mat matSrc = imread("qwer4.png");
Mat middle = picture_red(matSrc);
O_x1y1(middle, &xx1, &yy1, &xx2, &yy2);
x1 = xx1;
y1 = yy1;
x2 = xx2;
y2 = yy2;
imshow("原图", matSrc);
imshow("red", picture_red(matSrc));
cout << "红点:" << x1 << ", " << y1 << "; " << "红点1:" << x2 << ", " << y2 << endl;
waitKey();
return 0;
}

如有不足,望指点!

补充知识:opencv 识别网球 ,或者绿色的小球 输出重心坐标

我就废话不多说了,大家还是直接看代码吧!

代码语言:javascript
复制
void image_process(IplImage *image)
{
int iLowH =26; 
int iHighH = 69; 
int iLowS = 42;  
int iHighS = 206;  
int iLowV = 0; 
int iHighV = 198;
CvMemStorage* storage2 = cvCreateMemStorage();
CvSeq* contour3 = NULL;
CvMoments moments; 
CvMat *region; 
CvPoint pt1,pt2;
double m00 = 0, m10, m01, mu20, mu11, mu02, inv_m00; 
double a, b, c; 
int xc, yc; 
CvMemStorage* storage = cvCreateMemStorage();
CvSeq * circles=NULL;
// Circle cir[6];
CvPoint P0;
CvPoint CenterPoint;
// cvNamedWindow("win1"); 
//cvShowImage("win1",image);
//cvNamedWindow("image",CV_WINDOW_AUTOSIZE);//用于显示图像的窗口
//cvNamedWindow("hsv",CV_WINDOW_AUTOSIZE);	
//cvNamedWindow("saturation",CV_WINDOW_AUTOSIZE);
//cvNamedWindow("value",CV_WINDOW_AUTOSIZE);
//cvNamedWindow("pImg8u",1);
IplImage *hsv=cvCreateImage(cvGetSize(image),8,3);//给hsv色系的图像申请空间
IplImage *hue=cvCreateImage(cvGetSize(image),8,1); //色调
IplImage *saturation=cvCreateImage(cvGetSize(image),8,1);//饱和度
IplImage *value=cvCreateImage(cvGetSize(image),8,1);//亮度
IplImage *imgThresholded=cvCreateImage(cvGetSize(hue),8,1); 
cvNamedWindow("yuan",1);
cvCvtColor(image,hsv,CV_BGR2HSV);//将RGB色系转为HSV色系
cvShowImage("yuan",image);
//cvShowImage("hsv",hsv);
cvSplit(hsv, hue, 0, 0, 0 );//分离三个通道
cvSplit(hsv, 0, saturation, 0, 0 );
cvSplit(hsv, 0, 0, value, 0 );
int value_1=0;
cvInRangeS(
hsv, 
cvScalar(iLowH, iLowS, iLowV), 
cvScalar(iHighH, iHighS, iHighV),
imgThresholded
); 
cvNamedWindow("imgThresholded",1);
cvShowImage("imgThresholded",imgThresholded);
IplImage*pContourImg= cvCreateImage( cvGetSize(image), 8, 1 ); 
cvCopy(imgThresholded,pContourImg);
cvNamedWindow("pContourImg",1);
cvShowImage("pContourImg",pContourImg);
IplImage* dst = cvCreateImage( cvGetSize(image), 8, 3 ); 
CvMemStorage* storage3 = cvCreateMemStorage(0); 
CvSeq* contour = 0; 
// 提取轮廓 
int contour_num = cvFindContours(pContourImg, storage3, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 
cvZero(dst);    // 清空数组 
CvSeq *_contour = contour;  
double maxarea = 100; 
double minarea = 10; 
int m = 0; 
for( ; contour != 0; contour = contour- h_next )  
{  
double tmparea = fabs(cvContourArea(contour)); 
if(tmparea < minarea)   
{  
cvSeqRemove(contour, 0); // 删除面积小于设定值的轮廓 
continue; 
}  
CvRect aRect = cvBoundingRect( contour, 0 );  
if ((aRect.width/aRect.height)<1)  
{  
cvSeqRemove(contour, 0); //删除宽高比例小于设定值的轮廓 
continue; 
}  
if(tmparea   maxarea)  
{  
maxarea = tmparea; 
}  
m++; 
// 创建一个色彩值 
//  CvScalar color = CV_RGB( 0, 0, 255 ); 
/*  max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓 
如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种 
如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓 */ 
//  cvDrawContours(dst, contour, color, color, 0, 1, 8);  //绘制外部和内部的轮廓 
}  
contour = _contour; 
int count = 0; double tmparea=0;
for(; contour != 0; contour = contour- h_next) 
{  
count++; 
tmparea = fabs(cvContourArea(contour)); 
if (tmparea  = maxarea)  
{  
CvScalar color = CV_RGB( 0, 255, 0); 
cvDrawContours(dst, contour, color, color, -1, 1, 8); 
cout<<"222"<<endl;
cout<<"面积为"<<tmparea<<endl;
cout<<endl;
CvRect aRect = cvBoundingRect( contour, 0 ); 
//找重心
{
CvPoint2D32f center = cvPoint2D32f(0, 0);
int countOfPoint = 0;
for(int i = aRect.x; i < aRect.x + aRect.width; ++i){
for(int j = aRect.y; j < aRect.y + aRect.height; ++j){
if(*(image- imageData + image- widthStep * j + i) != 0){
center.x += i;
center.y += j;
countOfPoint++;
}
}
}
center.x /= countOfPoint;
center.y /= countOfPoint;
cout<<"重心坐标为x:"<<center.x<<endl;
cout<<"重心坐标为y:"<<center.y<<endl;
cvCircle(dst, cvPoint(center.x, center.y), 5, cvScalar(0, 255), 2);
}
}
// //Threshold the image
//  cvErode(imgThresholded,imgThresholded);
//  cvErode(imgThresholded,imgThresholded);
//cvErode(imgThresholded,imgThresholded);
//cvErode(imgThresholded,imgThresholded);	  
//IplImage* pImg8u=cvCloneImage(imgThresholded);
//cvCanny(pImg8u, pImg8u,40, 50, 5);
//cvShowImage("pImg8u",pImg8u);
//circles=cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT,
//2,  //最小分辨率,应当 =1
//pImg8u- height/15,  //该参数是让算法能明显区分的两个不同圆之间的最小距离
//80,  //用于Canny的边缘阀值上限,下限被置为上限的一半
//65,  //累加器的阀值
//25,   //最小圆半径 
//50   //最大圆半径
//);
}
cvShowImage( "contour", dst );
}

以上这篇使用opencv识别图像红色区域,并输出红色区域中心点坐标就是小编分享给大家的全部内容了,希望能给大家一个参考。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档