使用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 04 Python
Python实现端口复用实例代码
Jul 03 Python
python中的字典详细介绍
Sep 18 Python
详解Python中 __get__和__getattr__和__getattribute__的区别
Jun 16 Python
Python中functools模块函数解析
Mar 12 Python
Python实现基本数据结构中队列的操作方法示例
Dec 04 Python
python实现二叉查找树实例代码
Feb 08 Python
Python对切片命名的实现方法
Oct 16 Python
Python2和3字符编码的区别知识点整理
Aug 08 Python
浅谈Pytorch中的torch.gather函数的含义
Aug 18 Python
Python操作SQLite数据库过程解析
Sep 02 Python
python的slice notation的特殊用法详解
Dec 27 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
加强版phplib的DB类
2008/03/31 PHP
php中static静态变量的使用方法详解
2010/06/04 PHP
PHP实现恶意DDOS攻击避免带宽占用问题方法
2015/05/27 PHP
YII Framework框架教程之国际化实现方法
2016/03/14 PHP
Yii数据模型中rules类验证器用法分析
2016/07/15 PHP
php lcg_value与mt_rand生成0~1随机小数的效果对比分析
2017/04/05 PHP
PHP实现将优酷土豆腾讯视频html地址转换成flash swf地址的方法
2017/08/04 PHP
windows环境下使用Composer安装ThinkPHP5
2018/05/18 PHP
用正则xmlHttp实现的偷(转)
2007/01/22 Javascript
javascript CSS画图之基础篇
2009/07/29 Javascript
网络图片延迟加载实现代码 超越jquery控件
2010/03/27 Javascript
jquery写个checkbox——类似邮箱全选功能
2013/03/19 Javascript
js实现动画特效的文字链接鼠标悬停提示的方法
2015/03/02 Javascript
jquery实现浮动的侧栏实例
2015/06/25 Javascript
jQuery实现定时读取分析xml文件的方法
2015/07/16 Javascript
request请求获取参数的实现方法(post和get两种方式)
2016/09/27 Javascript
JavaScript实现仿Clock ISO时钟
2018/06/29 Javascript
webpack4 处理CSS的方法示例
2018/09/03 Javascript
React中使用外部样式的3种方式(小结)
2019/05/28 Javascript
javascript关于“时间”的一次探索
2019/07/24 Javascript
[02:11]完美世界DOTA2联赛10月28日赛事精彩集锦:来吧展示实力强劲
2020/10/29 DOTA
用实例说明python的*args和**kwargs用法
2013/11/01 Python
Python实现包含min函数的栈
2016/04/29 Python
全面理解Python中self的用法
2016/06/04 Python
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
对python遍历文件夹中的所有jpg文件的实例详解
2018/12/08 Python
Python将string转换到float的实例方法
2019/07/29 Python
python连接PostgreSQL数据库的过程详解
2019/09/18 Python
Python基于locals返回作用域字典
2020/10/17 Python
Python __slots__的使用方法
2020/11/15 Python
物业管理求职自荐信
2013/09/25 职场文书
中职应届生会计求职信
2013/10/23 职场文书
企业管理培训感言
2014/01/27 职场文书
2014县委书记四风对照检查材料思想汇报
2014/09/21 职场文书
2015国庆66周年宣传语
2015/07/14 职场文书
学法用法心得体会(2016推荐篇)
2016/01/21 职场文书