打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
通过HSV进行颜色分离
图片通常是以RGB格式存储,难以分离出颜色,可以转换到HSV空间进行颜色分离。
HSL 和 HSV(也叫HSB)是对RGB 色彩空间中点的两种有关系的表示,它们尝试描述比 RGB 更准确的感知颜色联系,并仍保持在计算上简单。
H指hue(色相)、S指saturation(饱和度)、L指lightness(亮度)、V指value(色调)、B指brightness(明度)。
色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色黄色等。
饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
明度(V),亮度(L),取0-100%。
HSL 和 HSV 二者都把颜色描述在圆柱坐标系内的点,这个圆柱的中心轴取值为自底部的黑色到顶部的白色而在它们中间是的灰色,绕这个轴的角度对应于“色相”,到这个轴的距离对应于“饱和度”,而沿着这个轴的高度对应于“亮度”,“色调”或“明度”。
这两种表示在用目的上类似,但在方法上有区别。二者在数学上都是圆柱,但 HSV(色相,饱和度,色调)在概念上可以被认为是颜色的倒圆锥体(黑点在下顶点,白色在上底面圆心),HSL 在概念上表示了一个双圆锥体和圆球体(白色在上顶点,黑色在下顶点,最大横切面的圆心是半程灰色)。注意尽管在 HSL 和 HSV 中“色相”指称相同的性质,它们的“饱和度”的定义是明显不同的。
因为 HSL 和 HSV 是设备依赖的 RGB 的简单变换,(h, s, l) 或 (h, s, v) 三元组定义的颜色依赖于所使用的特定红色绿色蓝色加法原色”。每个独特的 RGB 设备都伴随着一个独特的 HSL 和 HSV 空间。但是 (h, s, l) 或 (h, s, v) 三元组在被约束于特定 RGB 空间比如 sRGB 的时候就变成明确的了。
详见wiki百科:http://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4
般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。
H:  0— 180
S:  0— 255
V:  0— 255
此处把部分红色归为紫色范围:
绿
hmin
0
0
0
0
156
11
26
35
78
100
125
hmax
180
180
180
10
180
25
34;
77
99
124
155
smin
0
0
0
43
43
43
43
43
43
43
smax
255
43
30
255
255
255
255
255
255
255
vmin
0
46
221
46
46
46
46
46
46
46
vmax
46
220
255
255
255
255
255
255
255
255
[cpp]
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <cv.h>
#include <highgui.h>
#include <vector>
using namespace cv;
void sortCorners(std::vector<cv::Point2f>& corners,cv::Point2f center)
{
std::vector<cv::Point2f> top,bot;
for (unsigned int i =0;i< corners.size();i++)
{
if (corners[i].y<center.y)
{
top.push_back(corners[i]);
}
else
{
bot.push_back(corners[i]);
}
}
cv::Point2f tl = top[0].x > top[1].x ? top[1] : top[0];
cv::Point2f tr = top[0].x > top[1].x ? top[0] : top[1];
cv::Point2f bl = bot[0].x > bot[1].x ? bot[1] : bot[0];
cv::Point2f br = bot[0].x > bot[1].x ? bot[0] : bot[1];
corners.clear();
//注意以下存放顺序是顺时针,当时这里出错了,如果想任意顺序下文开辟的四边形矩阵注意对应
corners.push_back(tl);
corners.push_back(tr);
corners.push_back(br);
corners.push_back(bl);
}
int main(int argc, char* argv[])
{
Mat src = imread("greenCircle.jpg");
Mat dsc(src.size(),CV_8U,Scalar(0));
//
namedWindow("src", 1);
imshow("src", src);
//
//分离出绿色
Mat  hsv(src.size(),CV_8U,Scalar(0));
Mat  tmpH1(src.size(),CV_8U,Scalar(0));
Mat  tmpH4 (src.size(),CV_8U,Scalar(0));
Mat  tmpH2(src.size(),CV_8U,Scalar(0));
Mat  tmpH3(src.size(),CV_8U,Scalar(0));
blur(src,src,Size(3,3)); //高斯模糊
cvtColor(src, hsv, CV_BGR2HSV );//颜色转换
vector<Mat> mv;
split(hsv,mv);//分为3个通道
inRange(mv[0],Scalar(35,0.0,0,0),Scalar(77,0.0,0,0),tmpH1);
inRange(mv[1],Scalar(43.0,0.0,0,0),Scalar(255,0.0,0,0),tmpH2);
inRange(mv[2],Scalar(46,0.0,0,0),Scalar(255.0,0.0,0,0),tmpH3);
bitwise_and(tmpH3,tmpH2,tmpH2);
bitwise_and(tmpH1,tmpH2,tmpH1);
//blur(tmpH1,tmpH1,Size(3,3)); //高斯模糊
dsc = tmpH1.clone();
//处理dsc
blur(dsc,dsc,Size(3,3));
imshow("green", dsc);
vector<vector<Point>> contours;
vector<Point3f> circles;
findContours(dsc, contours,CV_RETR_EXTERNAL , CV_CHAIN_APPROX_NONE);
Mat OutlineImage(src.size(),CV_8U,Scalar(0));
// Eliminate too short or too long contours
int cmin = 50;  // minimum contour length
int cmax = 9999;
vector<vector<Point>>::const_iterator itc= contours.begin();
while (itc!=contours.end()) {
if (itc->size() < cmin || itc->size() > cmax)
itc= contours.erase(itc);
else
++itc;
}
drawContours(OutlineImage, contours,
-1,//draw all contours
CV_RGB(0,255,255),//in black
1);  //with a thickness of 2
//计算每条轮廓的中心(圆心)
vector<Point2f> corners;
if(contours.size() != 4){
std::cout<<"contours wrong!"<<std::endl;
return -1;
}
for(int i=0;i<contours.size();i++)
{
float sum_x = 0;
float sum_y = 0;
float length = contours[i].size();
for(int j=0;j<length;j++)
{
sum_x += contours[i][j].x;
sum_y += contours[i][j].y;
}
corners.push_back(Point2f(sum_x/length,sum_y/length));
}
Point2f center;
for(int i=0;i<corners.size();i++)
{
circle(src,Point2f(corners[i].x,corners[i].y),3,CV_RGB(255,0,0),2);
center += corners[i];
}
center *= (1./corners.size());
sortCorners(corners,center);
Mat quad = Mat::zeros(320,240,CV_8UC3);//校正后图片
//校正过的图片从320*240
//corners of the destination image
std::vector<Point2f> quad_pts;
quad_pts.push_back(Point2f(0,0));
quad_pts.push_back(Point2f(quad.cols,0));//(220,0)
quad_pts.push_back(Point2f(quad.cols,quad.rows));//(220,300)
quad_pts.push_back(Point2f(0,quad.rows));
// Get transformation matrix
Mat transmtx = getPerspectiveTransform(corners,quad_pts);   //求源坐标系(已畸变的)与目标坐标系(转换后的)的转换矩阵
// Apply perspective transformation透视转换
warpPerspective(src,quad,transmtx,quad.size());
namedWindow("quadrilateral",1);
imshow("quadrilateral",quad);
waitKey(0);
return 0;
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
opencv颜色识别学习总结
基于distanceTransform-距离变换的区域中心提取
OpenCV-绘制旋转矩形
OpenCV学习28
基于OpenCV的车辆变道检测
opencv 截取轮廓中的图像
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服