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


Posted in Python onJune 02, 2020

适用小白,大佬勿喷

个人配置:vs2013 ; opencv 3.0 ;

直接上效果图

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

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

下面是代码:

#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 识别网球 ,或者绿色的小球 输出重心坐标

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

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识别图像红色区域,并输出红色区域中心点坐标就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python递归函数定义与用法示例
Jun 02 Python
python中reduce()函数的使用方法示例
Sep 29 Python
如何在sae中设置django,让sae的工作环境跟本地python环境一致
Nov 21 Python
python 输出上个月的月末日期实例
Apr 11 Python
python监控进程状态,记录重启时间及进程号的实例
Jul 15 Python
Python代码使用 Pyftpdlib实现FTP服务器功能
Jul 22 Python
python3使用print打印带颜色的字符串代码实例
Aug 22 Python
关于pytorch中全连接神经网络搭建两种模式详解
Jan 14 Python
Tensorflow 多线程与多进程数据加载实例
Feb 05 Python
Django Admin 上传文件到七牛云的示例代码
Jun 20 Python
python进行OpenCV实战之画图(直线、矩形、圆形)
Aug 27 Python
Python加密技术之RSA加密解密的实现
Apr 08 Python
什么是Python中的顺序表
Jun 02 #Python
opencv 实现特定颜色线条提取与定位操作
Jun 02 #Python
Python爬虫入门有哪些基础知识点
Jun 02 #Python
Python实现进度条和时间预估的示例代码
Jun 02 #Python
python爬虫容易学吗
Jun 02 #Python
基于Python词云分析政府工作报告关键词
Jun 02 #Python
使用OpenCV获取图像某点的颜色值,并设置某点的颜色
Jun 02 #Python
You might like
php截取utf-8中文字符串乱码的解决方法
2010/03/29 PHP
PHP 显示客户端IP与服务器IP的代码
2010/10/12 PHP
PHP spl_autoload_register实现自动加载研究
2011/12/06 PHP
php编写的一个E-mail验证类
2015/03/25 PHP
php实现简单的上传进度条
2015/11/17 PHP
document.all的一个比较完整的总结及案例
2013/01/31 Javascript
解决jquery1.9不支持browser对象的问题
2013/11/13 Javascript
动态读取JSON解析键值对的方法
2014/06/03 Javascript
JS实现关键字搜索时的相关下拉字段效果
2014/08/05 Javascript
Jquery实现由下向上展开效果的例子
2014/12/08 Javascript
JQuery中属性过滤选择器用法实例分析
2015/05/18 Javascript
JavaScript File API实现文件上传预览
2016/02/02 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
2017/02/10 Javascript
react.js 获取真实的DOM节点实例(必看)
2017/04/17 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
Nodejs对postgresql基本操作的封装方法
2019/02/20 NodeJs
详解node和ES6的模块导出与导入
2020/02/19 Javascript
基于js实现逐步显示文字输出代码实例
2020/04/02 Javascript
js绘制一条直线并旋转45度
2020/08/21 Javascript
javascript实现前端分页功能
2020/11/26 Javascript
基于JavaScript实现随机点名器
2021/02/25 Javascript
[51:15]2014 DOTA2国际邀请赛中国区预选赛 Orenda VS LGD-GAMING
2014/05/22 DOTA
Python Paramiko模块的使用实际案例
2018/02/01 Python
Python 隐藏输入密码时屏幕回显的实例
2019/02/19 Python
python 实现查询Neo4j多节点的多层关系
2019/12/23 Python
python 中的9个实用技巧,助你提高开发效率
2020/08/30 Python
python 如何用urllib与服务端交互(发送和接收数据)
2021/03/04 Python
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
商务英语求职自荐信范文
2013/12/24 职场文书
中学教师管理制度
2014/01/14 职场文书
校运会广播稿100字
2014/01/27 职场文书
关于读书的演讲稿400字
2014/08/27 职场文书
佛光寺导游词
2015/02/10 职场文书
2015年计划生育责任书
2015/05/08 职场文书
《陶罐和铁罐》教学反思
2016/03/03 职场文书
vue如何使用模拟的json数据查看效果
2022/03/31 Vue.js