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
#include
#include
#include
#include
#include
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);elsecout << "找不到颜色" << endl;}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
