文章目录
- opencv3颜色识别(C++)
- 目标
- 思路
- 1. 读取图像
- 2. 对比度调整(直方图均衡)
- 3.RGB颜色分类
- 4.形态学去噪声
- 代码
- 结果
- 参考
opencv3颜色识别(C++)
目标
给定一幅图像,可以是读取指定文件或者从摄像机获取,识别图像中的颜色。这里我们只识别8种颜色,包括黑、红、绿、黄、蓝、紫、靛、白。这8种颜色是RGB颜色空间中位于8个顶点的颜色。
思路
1. 读取图像
读取摄像机的一帧
VideoCapture cap(0); //capture the video from web cam
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
Mat imgOriginal;
bool bSuccess = cap.read(imgOriginal); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
读取指定路径的图片
Mat imgOriginal = imread("1.jpg");
2. 对比度调整(直方图均衡)
- 这一步是可选步骤,根据情况选择是否使用。
- 类似于灰度图像使用直方图均衡调整对比度。根据冈萨雷斯的书,对于彩色图像,一般不建议在RGB空间中分别对三种通道进行直方图均衡,因为这样可能会引入一些特殊的颜色。一般的做法是将RGB空间转换到HSI空间或者HSV空间。然后对强度分量或者明度分量进行直方图均衡。关于这三种颜色空间的区别和联系可以参考博客RGB、HSV、HSI颜色空间。
- 直方图均衡完成以后再转回值RGB颜色空间。
vector<Mat> hsvSplit; //创建向量容器,存放HSV的三通道数据
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
split(imgHSV, hsvSplit); //分类原图像的HSV三通道
equalizeHist(hsvSplit[2], hsvSplit[2]); //对HSV的亮度通道进行直方图均衡
merge(hsvSplit, imgHSV); //合并三种通道
cvtColor(imgHSV, imgBGR, COLOR_HSV2BGR); //将HSV空间转回至RGB空间,为接下来的颜色识别做准备
3.RGB颜色分类
- 将RGB颜色立方体分解为等大的8个小正方体,判断输入的RGB颜色值属于哪一个小块,则该RGB的颜色就是该小块的颜色。8个小正方体的颜色分别对应上述的8种颜色。
- 注意opencv中图像的彩色通道顺序为BGR,而不是RGB。
- 8种颜色BGR值分别为
颜色 | BGR |
---|
黑色 | 0 0 0 |
红色 | 0 0 255 |
绿色 | 0 255 0 |
黄色 | 0 255 255 |
蓝色 | 255 0 0 |
紫色 | 255 0 255 |
靛色 | 255 255 0 |
白色 | 255 255 255 |
- 若输入的BRG为(x,y,z),则分别对三个变量与127作比较,确定其属于哪一个小块。
Mat imgThresholded;
int ctrl = 0; //该变量用于控制识别何种颜色
switch(ctrl)
{
case 0:
{
inRange(imgBGR, Scalar(128, 0, 0), Scalar(255, 127, 127), imgThresholded); //蓝色
//这个函数将BGR图像中满足在(128, 0, 0)与(255, 127, 127)范围内的像素点选出来,并将该范围内的像素值赋值为白色,
//其他区域赋值为黑色,并将这个二值图像存入 imgThresholded。
break;
}
case 1:
{
inRange(imgBGR, Scalar(128, 128, 128), Scalar(255, 255, 255), imgThresholded); //白色
break;
}
case 2:
{
inRange(imgBGR, Scalar(128, 128, 0), Scalar(255, 255, 127), imgThresholded); //靛色
break;
}
case 3:
{
inRange(imgBGR, Scalar(128, 0, 128), Scalar(255, 127, 255), imgThresholded); //紫色
break;
}
case 4:
{
inRange(imgBGR, Scalar(0, 128, 128), Scalar(127, 255, 255), imgThresholded); //黄色
break;
}
case 5:
{
inRange(imgBGR, Scalar(0, 128, 0), Scalar(127, 255, 127), imgThresholded); //绿色
break;
}
case 6:
{
inRange(imgBGR, Scalar(0, 0, 128), Scalar(127, 127, 255), imgThresholded); //红色
break;
}
case 7:
{
inRange(imgBGR, Scalar(0, 0, 0), Scalar(127, 127, 127), imgThresholded); //黑色
break;
}
}
4.形态学去噪声
- 使用开操作和闭操作去除二值化图像中的噪声。原理可以参考冈萨雷斯的书。
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); //设置结构元
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element); //开操作
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element); //闭操作
代码
#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
VideoCapture cap(0); //capture the video from web cam
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
namedWindow("control", 1);
int ctrl = 0;
createTrackbar("ctrl", "control", &ctrl, 7);
while (true)
{
Mat imgOriginal;
bool bSuccess = cap.read(imgOriginal); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
// imgOriginal = imread("4.jpg");
Mat imgHSV, imgBGR;
Mat imgThresholded;
if(0)
{
vector<Mat> hsvSplit; //创建向量容器,存放HSV的三通道数据
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
split(imgHSV, hsvSplit); //分类原图像的HSV三通道
equalizeHist(hsvSplit[2], hsvSplit[2]); //对HSV的亮度通道进行直方图均衡
merge(hsvSplit, imgHSV); //合并三种通道
cvtColor(imgHSV, imgBGR, COLOR_HSV2BGR); //将HSV空间转回至RGB空间,为接下来的颜色识别做准备
}
else
{
imgBGR = imgOriginal.clone();
}
switch(ctrl)
{
case 0:
{
inRange(imgBGR, Scalar(128, 0, 0), Scalar(255, 127, 127), imgThresholded); //蓝色
break;
}
case 1:
{
inRange(imgBGR, Scalar(128, 128, 128), Scalar(255, 255, 255), imgThresholded); //白色
break;
}
case 2:
{
inRange(imgBGR, Scalar(128, 128, 0), Scalar(255, 255, 127), imgThresholded); //靛色
break;
}
case 3:
{
inRange(imgBGR, Scalar(128, 0, 128), Scalar(255, 127, 255), imgThresholded); //紫色
break;
}
case 4:
{
inRange(imgBGR, Scalar(0, 128, 128), Scalar(127, 255, 255), imgThresholded); //黄色
break;
}
case 5:
{
inRange(imgBGR, Scalar(0, 128, 0), Scalar(127, 255, 127), imgThresholded); //绿色
break;
}
case 6:
{
inRange(imgBGR, Scalar(0, 0, 128), Scalar(127, 127, 255), imgThresholded); //红色
break;
}
case 7:
{
inRange(imgBGR, Scalar(0, 0, 0), Scalar(127, 127, 127), imgThresholded); //黑色
break;
}
}
imshow("形态学去噪声前", imgThresholded);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element);
morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element);
imshow("Thresholded Image", imgThresholded); //show the thresholded image
imshow("直方图均衡以后", imgBGR);
imshow("Original", imgOriginal); //show the original image
char key = (char)waitKey(300);
if (key == 27)
break;
}
return 0;
}
结果
- 通过滑动条控制识别和种颜色
- 对该图像进行颜色识别
- 识别蓝色
- 识别红色
参考
https://blog.csdn.net/zhenguo26/article/details/82803241
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)