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;

}

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!要将指定色块均分,可以按照以下步骤进行: 1. 首先使用OpenCV中的cv2.imread()函数读取图像,并使用cv2.cvtColor()函数将其转换为HSV颜色空间。 2. 对于指定的颜色块,可以使用cv2.inRange()函数创建一个掩码,将图像中的非颜色块部分过滤掉。 3. 使用cv2.findContours()函数查找颜色块轮廓,并使用cv2.boundingRect()函数确定其边界框。 4. 计算边界框的中心点,并按照所需数量和方向,将其分成均匀的子区域。 5. 对于每个子区域,可以使用cv2.rectangle()函数绘制边界框。 6. 最后,使用cv2.imshow()函数显示结果图像。 以下是一个示例代码,可以将一个红色矩形均分为4个子矩形: ``` import cv2 import numpy as np # 读取图像并转换为HSV颜色空间 img = cv2.imread('image.jpg') hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义红色的HSV范围 lower_red = np.array([0, 50, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv, lower_red, upper_red) lower_red = np.array([170, 50, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv, lower_red, upper_red) mask = cv2.bitwise_or(mask1, mask2) # 查找红色矩形的轮廓并确定其边界框 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) x, y, w, h = cv2.boundingRect(contours[0]) # 将矩形分成4个子矩形 sub_w = int(w / 2) sub_h = int(h / 2) centers = [(x + sub_w, y + sub_h), (x + sub_w, y + 3 * sub_h), (x + 3 * sub_w, y + sub_h), (x + 3 * sub_w, y + 3 * sub_h)] # 绘制子矩形 for center in centers: x, y = center cv2.rectangle(img, (x - sub_w, y - sub_h), (x + sub_w, y + sub_h), (0, 255, 0), 2) # 显示结果图像 cv2.imshow('Result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 希望能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值