OpenCv的HSV颜色空间学习
虽然我们这张图的方框并不是彩色的,但是以后肯定会遇到彩色的问题所以先学习一下
H——Hue即色相,就是我们平时所说的红、绿,如果你分的更细的话可能还会有洋红、草绿等等;在HSV模型中,用度数来描述色相,其中红色对应0度,绿色对应120度,蓝色对应240度。
S——Saturation即饱和度,色彩的深浅度(0-100%) ,对于一种颜色比如红色,我们可以用浅红——大红——深红——红得发紫等等语言来描述它,对应在画水彩的时候即一种颜料加上不同分量的水形成不同的饱和度。
V——Value即色调,纯度,色彩的亮度(0-100%) ,这个在调整屏幕亮度的时候比较常见。
注:在模型2中:
H是色彩点在对应圆形切面上与红色半径(对于H=0度)所形成的圆心角。
V是色彩点所在圆形切面到圆锥顶点的距离。在顶面上V=1 顶点V=0
S是色彩点到所在圆形切面圆心的距离与该圆半径的比例值,在圆锥表面上S=1,在圆心处S=0
有如下结论:
当S=1 V=1时,H所代表的任何颜色被称为纯色;
当S=0时,即饱和度为0,颜色最浅,最浅被描述为灰色(灰色也有亮度,黑色和白色也属于灰色),灰色的亮度由V决定,此时H无意义;
当V=0时,颜色最暗,最暗被描述为黑色,因此此时H(无论什么颜色最暗都为黑色)和S(无论什么深浅的颜色最暗都为黑色)均无意义。
与上述HSV颜色系统不同的是,如果直接使用OpenCV中cvtColor函数,并设置参数为CV_BGR2HSV,那么所得的H、S、V值范围分别是[0,180),[0,255),[0,255),而非[0,360],[0,1],[0,1];这时我们可以查下面的表格来确定颜色的大致区间。
可以用以下代码查看:
Mat src = imread("test.jpg");
Mat hsv;
cvtColor(src, hsv, CV_BGR2HSV); //直接转换
cout<<hsv<<endl; 可以直接在控制台输出hsv查看结果< code></hsv<<endl;>
任务
下图为对包含装甲板的图像处理后得到的mask,对于该图,提取并筛选出装甲板两个灯柱的轮廓,并标出装甲板的中心。
先是根据东南大学的开源代码折腾了半天,一直没折腾出来,代码如下
cv::RotatedRect &adjustRec(cv::RotatedRect &rec)
{
using std::swap;
float &width = rec.size.width;
float &height = rec.size.height;
float &angle = rec.angle;
while (angle >= 90.0)
angle -= 180.0;
while (angle < -90.0)
angle += 180.0;
if (angle >= 45.0)
{
swap(width, height);
angle -= 90.0;
}
else if (angle < -45.0)
{
swap(width, height);
angle += 90.0;
}
return rec;
}
int main(int argc, char **argv)
{
Mat dst = imread("C:/Users/86139/Desktop/target.png");
vector<vector<point>> Light_Contour; // 发现的轮廓
vector<rotatedrect> vContour;
vector<rotatedrect> vRec;
findContours(dst, Light_Contour, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 寻找轮廓
for (int64 i = 0; i < Light_Contour.size(); i++)
{
float Light_Contour_Area = contourArea(Light_Contour[i]);
if (Light_Contour_Area < 15 || Light_Contour[i].size() <= 10) continue; 用椭圆拟合区域得到外接矩形 rotatedrect light_rec="fitEllipse(Light_Contour[i]);" 这里限制了角度 if (light_rec.angle> 10)
continue;
// 长宽比和轮廓面积比限制
if (Light_Rec.size.width / Light_Rec.size.height > 1.5 || Light_Contour_Area / Light_Rec.size.area() < 0.5)
continue;
// 扩大灯柱的面积
Light_Rec.size.height *= 1.1;
Light_Rec.size.width *= 1.1;
vContour.push_back(Light_Rec);
}
for (size_t i = 0; i < vContour.size(); i++)
{
for (size_t j = i + 1; j < vContour.size(); j++)
{
//判断是否为相同灯条
float Contour_angle = abs(vContour[i].angle - vContour[j].angle); //角度差
if (Contour_angle >= 7)
continue;
//长度差比率
float Contour_Len1 = abs(vContour[i].size.height - vContour[j].size.height) /
max(vContour[i].size.height, vContour[j].size.height);
//宽度差比率
float Contour_Len2 = abs(vContour[i].size.width - vContour[j].size.width) /
max(vContour[i].size.width, vContour[j].size.width);
if (Contour_Len1 > 0.25 || Contour_Len2 > 0.25)
continue;
//装甲板筛选
RotatedRect Rect;
Rect.center.x = (vContour[i].center.x + vContour[j].center.x) / 2.; // x坐标
Rect.center.y = (vContour[i].center.y + vContour[j].center.y) / 2.; // y坐标
Rect.angle = (vContour[i].angle + vContour[j].angle) / 2.; //角度
float nh, nw, yDiff, xDiff;
nh = (vContour[i].size.height + vContour[j].size.height) / 2; //高度
// 宽度
nw = sqrt((vContour[i].center.x - vContour[j].center.x) * (vContour[i].center.x - vContour[j].center.x) + (vContour[i].center.y - vContour[j].center.y) * (vContour[i].center.y - vContour[j].center.y));
float ratio = nw / nh; //匹配到的装甲板的长宽比
xDiff = abs(vContour[i].center.x - vContour[j].center.x) / nh; // x差比率
yDiff = abs(vContour[i].center.y - vContour[j].center.y) / nh; // y差比率
if (ratio < 1.0 || ratio > 5.0 || xDiff < 0.5 || yDiff > 2.0)
continue;
Rect.size.height = nh;
Rect.size.width = nw;
vRec.push_back(Rect);
Point2f point1;
Point2f point2;
point1.x = vContour[i].center.x;
point1.y = vContour[i].center.y + 20;
point2.x = vContour[j].center.x;
point2.y = vContour[j].center.y - 20;
int xmidnum = (point1.x + point2.x) / 2;
int ymidnum = (point1.y + point2.y) / 2;
Rect.center.x = filter(Rect.center.x, xmidnum, DELAT_MAX);
Rect.center.y = filter(Rect.center.y, ymidnum, DELAT_MAX);
Scalar color(rand() & 255, rand() & 255, rand() & 255);
rectangle(dst, point1, point2, color, 2);
circle(dst, Rect.center, 10, color);
imshow("Rect", dst);
waitKey(0);
}
}
return 0;
}</=></rotatedrect></rotatedrect></vector<point>
在用cmake编译时遇到了:warning C4819: 该文件包含不能在当前代码页(936)中表示的字符
在CMakeList.txt中加入如下内容:
add_compile_options("$<$<c_compiler_id:msvc>:/utf-8>")
add_compile_options("$<$<cxx_compiler_id:msvc>:/utf-8>")</$<cxx_compiler_id:msvc></$<c_compiler_id:msvc>
且必须位于add_executable之前
还有一个基础知识错误:warning C4018: “
Original: https://blog.csdn.net/weixin_47259513/article/details/125923306
Author: 世界函数
Title: 视觉培训3 装甲板识别
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/701284/
转载文章受原作者版权保护。转载请注明原作者出处!