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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章