OPENCV绘制指定色块的轮廓和形心

效果展示:
在这里插入图片描述
在这里插入图片描述
思路是将图片转化为hsv格式,然后用inRange函数变为黑白二值化图像,二值化图像有噪点时用开操作闭操作去除,用canny算子检测边缘,findContours函数寻找轮廓,再计算轮廓矩 和中心,再绘制轮廓和形心
图片转化为hsv格式
在这里插入图片描述
图为各种颜色的hsv值对应表

cvtColor(src, hsv, CV_BGR2HSV); //直接转换为hsv

贴上详细介绍hsv的博文
在这里插入图片描述
HSV效果图

inRange函数

//inRange函数可以将指定颜色转化为白色,其他颜色转化为黑色
		inRange(hsv, Scalar(26, 43, 46), Scalar(34, 255, 255), temp);

第一个变量为输入的hsv图片,第二个是某颜色对应的hsv_min值,第三个是某颜色对应的hsv_max值,第四个是输出的图像
在这里插入图片描述
效果图

Canny函数

//对得到的二值化图像进行边缘检测
	Canny(temp, temp, 20, 80, 3, false);

在这里插入图片描述
效果图

寻找轮廓

findContours(temp, contours, hierarchy, RETR_TREE, 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] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
	}

绘制轮廓标和标定形心


	Mat drawing = Mat::zeros(temp.size(), CV_8UC3);
	for (int i = 0; i < contours.size(); i++)
	{
		Scalar color = Scalar(0, 0, 0);
		//第一个变量用初始图像可以将轮廓绘制到原图上
		drawContours(src, contours, i, color, 2, 8, hierarchy, 0, Point(0, 0));
		//指的是标定形心,第一个变量用初始图像可以将形心绘制到原图上
		circle(src, mc[i], 1, Scalar(0, 0, 0), -1, 6, 0);      //画中心圆

	}

代码少了降噪部分,图是自己画的比较清晰没有噪点等问题就没有写。
除此之外还出现了一些问题
问题
在这里插入图片描述
指点蓝色时没达到效果。
在这里插入图片描述
标定紫色时星星的形心不在中间。
以上两个问题还想不到解决方法。。。

最后

贴上findContours和drawContours使用介绍
完整代码如下:

#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include <opencv2\imgproc\types_c.h>
using namespace std;
using namespace cv;
Mat hsv;
Mat temp;
string colour;
//声明Choose函数。
void Choose();

//主函数
int main()
{

	//输入想要的颜色
	cout << "请输入颜色:" << endl;
	cin >> colour;

	//载入并显示图像
	Mat src = imread("1.jpg");
	imshow("原图", src);

	//RGB转化为hsv图像,方便下一步提取指定颜色
	cvtColor(src, hsv, CV_BGR2HSV); //直接转换
	imshow("1", hsv);
	//定义一个选择函数,一种颜色对应一个hsv范围
	Choose();
	imshow("2", temp);

	//对得到的二值化图像进行边缘检测
	Canny(temp, temp, 20, 80, 3, false);
	imshow("3", temp);

	//变量声明
	std::vector<std::vector<Point>> contours;
	std::vector<Vec4i> hierarchy;

	//寻找轮廓
	findContours(temp, contours, hierarchy, RETR_TREE, 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] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
	}
	//绘制轮廓标定形心
	Mat drawing = Mat::zeros(temp.size(), CV_8UC3);
	for (int i = 0; i < contours.size(); i++)
	{
		Scalar color = Scalar(0, 0, 0);
		//第一个变量用初始图像可以将轮廓绘制到原图上
		drawContours(src, contours, i, color, 2, 8, hierarchy, 0, Point(0, 0));
		//指的是标定形心
		circle(src, mc[i], 1, Scalar(0, 0, 0), -1, 6, 0);      //画中心圆

	}

	imshow("output", src);


	waitKey(0);
	return(0);
}

//选择函数
void Choose()

{
	
	if (colour == "黄")
		//inRange函数可以将指定颜色转化为白色,其他颜色转化为黑色
		inRange(hsv, Scalar(26, 43, 46), Scalar(34, 255, 255), temp);
	
	else if (colour == "红")
	
		inRange(hsv, Scalar(156, 43, 46), Scalar(180, 255, 255), temp);
	
	else if (colour == "绿")
	
		inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), temp);
	
	else if (colour == "蓝")
	
		inRange(hsv, Scalar(100, 43, 46), Scalar(124, 255, 255), temp);
	
	else if (colour == "黑")
	
		inRange(hsv, Scalar(0, 0, 0), Scalar(180, 255, 46), temp);
	
	else if (colour == "紫")
	
		inRange(hsv, Scalar(125, 43, 46), Scalar(155, 255, 255), temp);

	else if (colour == "橙")
	
		inRange(hsv, Scalar(11, 43, 46), Scalar(25, 255, 255), temp);

	
	else
		cout << "找不到颜色" << endl;

}

猜你喜欢

转载自blog.csdn.net/lllllllllljg/article/details/104097811