opencv3颜色识别(C++)

文章目录

  • 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 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 
#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 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;

}

结果

  • 通过滑动条控制识别和种颜色
    opencv3颜色识别(C++)_第1张图片
  • 对该图像进行颜色识别
    opencv3颜色识别(C++)_第2张图片
  • 识别蓝色
    opencv3颜色识别(C++)_第3张图片
  • 识别红色
    opencv3颜色识别(C++)_第4张图片

参考

https://blog.csdn.net/zhenguo26/article/details/82803241

你可能感兴趣的:(OpenCV)