使用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之入门(三)序列
May 25 Python
Python 字典dict使用介绍
Nov 30 Python
Python中的os.path路径模块中的操作方法总结
Jul 07 Python
Python中的日期时间处理详解
Nov 17 Python
Python编程实现正则删除命令功能
Aug 30 Python
python识别图像并提取文字的实现方法
Jun 28 Python
Python 多线程搜索txt文件的内容,并写入搜到的内容(Lock)方法
Aug 23 Python
Python time库基本使用方法分析
Dec 13 Python
python super函数使用方法详解
Feb 14 Python
Python json模块与jsonpath模块区别详解
Mar 05 Python
python tkinter的消息框模块(messagebox,simpledialog)
Nov 07 Python
详解Python为什么不用设计模式
Jun 24 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之预定义接口详解
2015/07/29 PHP
CodeIgniter记录错误日志的方法全面总结
2016/05/17 PHP
ThinkPHP框架表单验证操作方法
2017/07/19 PHP
Laravel框架中自定义模板指令总结
2017/12/17 PHP
js中的push和join方法使用介绍
2013/10/08 Javascript
JavaScript中计算网页中某个元素的位置
2015/06/10 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
2016/04/18 Javascript
JS不用正则验证输入的字符串是否为空(包含空格)的实现代码
2016/06/14 Javascript
学习Angular中作用域需要注意的坑
2016/08/17 Javascript
js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)
2017/02/13 Javascript
基于vue.js轮播组件vue-awesome-swiper实现轮播图
2017/03/17 Javascript
JavaScript数组和对象的复制
2017/03/21 Javascript
微信小程序页面间通信的5种方式
2017/03/31 Javascript
Javascript中类式继承和原型式继承的实现方法和区别之处
2017/04/25 Javascript
基于Three.js实现360度全景图片
2018/12/30 Javascript
vue组件通信传值操作示例
2019/01/08 Javascript
JS 获取文件后缀,判断文件类型(比如是否为图片格式)
2020/05/09 Javascript
修改NPM全局模式的默认安装路径的方法
2020/12/15 Javascript
[02:43]中国五虎出征TI3视频
2013/08/02 DOTA
非递归的输出1-N的全排列实例(推荐)
2017/04/11 Python
Python基于time模块求程序运行时间的方法
2017/09/18 Python
Odoo中如何生成唯一不重复的序列号详解
2018/02/10 Python
python通过微信发送邮件实现电脑关机
2018/06/20 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
在Django中预防CSRF攻击的操作
2020/03/13 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
2020/11/24 Python
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
TripAdvisor斯洛伐克:阅读评论、比较价格和酒店预订
2018/04/25 全球购物
迷你唐卡软皮鞋:Minnetonka Moccasin
2018/05/01 全球购物
青年文明号创建承诺
2014/03/31 职场文书
宾馆仓管员岗位职责
2014/07/27 职场文书
音乐教师求职信范文
2015/03/20 职场文书
社区活动总结范文
2015/05/07 职场文书
Python中异常处理用法
2021/11/27 Python
frg-100简单操作(设置)说明
2022/04/05 无线电
Win10服务主机占用内存怎么办?Win10服务主机进程占用大量内存解决方法
2022/09/23 数码科技