OpenCV入门(C++/Python)- 使用OpenCV色彩空间(七)
创始人
2024-04-20 16:52:21
0

在本教程中,了解计算机视觉中使用的流行色彩空间,并将其用于基于颜色的分割。

使用OpenCV色彩空间

  • 不同的颜色空间
    • RGB颜色空间
    • LAB颜色空间
    • YCrCB 颜色空间
    • HSV颜色空间
  • 如何使用这些颜色空间进行分割
    • 简单方法

文章内容如下:

  • 首先,我们将了解如何在OpenCV中读取图像并将其转换为不同的颜色空间,并了解每个颜色空间的不同通道为我们提供了哪些新信息。
  • 我们将应用掩码,来做一个简单的颜色分割算法,在算法中使用系统的方法来选择指定的颜色:1.正确的颜色空间。2.分割的正确阈值。

不同的颜色空间

在本节中,将介绍计算机视觉中使用的一些重要颜色空间。

通过加载一个立方体的图像。将讲解不同的颜色空间。

首先是,Opencv默认情况下,它将以BGR格式加载。我们可以使用OpenCV函数cvtColor()在不同的颜色空间之间进行转换,稍后将显示。

Python

#python
img = cv2.imread('cube.jpg')

C++

img = cv::imread('cube.jpg')

在这里插入图片描述

RGB颜色空间

RGB颜色空间具有以下属性

  • 它是一个加法颜色空间,其中颜色是通过红色、绿色和蓝色值的线性组合获得的。
  • 这三个通道与撞击表面的光量相关。

让我们将这两个图像分成R、G和B分量,并观察它们,以获得对颜色空间的更多了解。

在这里插入图片描述

LAB颜色空间

Lab颜色空间有三个通道

  1. L–亮度(强度)
  2. a–颜色成分范围从绿色到红色
  3. b–从蓝色到黄色的颜色成分

Lab颜色空间与RGB颜色空间非常不同。在RGB颜色空间中,颜色信息被分成三个通道,但相同的三个通道也编码亮度信息。但在Lab颜色空间中,L通道独立于颜色信息,仅对亮度进行编码。其他两个通道编码颜色。

它具有以下属性。

  • 感知均匀的颜色空间,近似于我们感知颜色的方式。
  • 独立于设备(捕获或显示)。
  • 在Adobe Photoshop中广泛使用。
  • 与RGB颜色空间相关的是一个复杂的变换方程。

让我们看看Lab颜色空间中的两幅图像,它们被分成三个通道。

Python

#python
LAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

C++

//C++
cv::cvtColor(img, LAB, cv::COLOR_BGR2LAB);

在这里插入图片描述

YCrCB 颜色空间

YCrCb颜色空间源自RGB颜色空间,具有以下三种通道。

  1. 从RGB获得的亮度经过Y–伽马校正后的分量。
  2. Cr=R–Y(红色分量距离Luminance距离)。
  3. Cb=B–Y(蓝色分量距离Luminance距离)。

此颜色空间具有以下属性。

  • 将亮度和色度分量分离到不同的通道中。
  • 主要用于电视传输的压缩(Cr和Cb成分)。

Python

#python
YCB = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)

C++

//C++
cv::cvtColor(img, YCB, cv::COLOR_BGR2YCrCb);

在这里插入图片描述

HSV颜色空间

HSV颜色空间包含以下三个通道

  • H–色调(颜色波长)。
  • S–饱和度(颜色的纯度/色调)。
  • V–值(强度)。

其中H通道可以用它来描述颜色最为直观
魔方图像的H、S和V分量如下所示。
Python

#python
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

C++

//C++
cv::cvtColor(img,hsv, cv::COLOR_BGR2HSV);

在这里插入图片描述

如何使用这些颜色空间进行分割

简单方法

现在我们已经对不同的颜色空间有了一些了解,让我们首先尝试使用它们来检测立方体中的蓝色。

在这里插入图片描述

应用阈值进行分割
从图像中所有像素,提取值接近蓝色的像素。我们可以设定一个蓝色颜色范围,来更可能获取到所有的蓝色像素

再使用opencv.inRange()函数查找这个范围内所有的像素,再使用bitwise_and运算从图像中获取这部分像素。(也就是除蓝色范围内的所有像素,其他所有内容去掉)

还要注意,为了将一个像素转换为另一个颜色空间,我们首先需要将1D矩阵转换为3D矩阵。

Python

import cv2
import  numpy as npbright = cv2.imread('data/cube.jpg')
brightLAB = cv2.cvtColor(bright, cv2.COLOR_BGR2LAB)
brightYCB = cv2.cvtColor(bright, cv2.COLOR_BGR2YCrCb)
brightHSV = cv2.cvtColor(bright, cv2.COLOR_BGR2HSV)bgr = [255, 50, 50]
thresh = 50minBGR = np.array([bgr[0] - thresh, bgr[1] - thresh, bgr[2] - thresh])
maxBGR = np.array([bgr[0] + thresh, bgr[1] + thresh, bgr[2] + thresh])maskBGR = cv2.inRange(bright,minBGR,maxBGR)
resultBGR = cv2.bitwise_and(bright, bright, mask = maskBGR)#convert 1D array to 3D, then convert it to HSV and take the first element
# this will be same as shown in the above figure [65, 229, 158]
hsv = cv2.cvtColor( np.uint8([[bgr]] ), cv2.COLOR_BGR2HSV)[0][0]minHSV = np.array([hsv[0] - thresh, hsv[1] - thresh, hsv[2] - thresh])
maxHSV = np.array([hsv[0] + thresh, hsv[1] + thresh, hsv[2] + thresh])maskHSV = cv2.inRange(brightHSV, minHSV, maxHSV)
resultHSV = cv2.bitwise_and(brightHSV, brightHSV, mask = maskHSV)#convert 1D array to 3D, then convert it to YCrCb and take the first element
ycb = cv2.cvtColor( np.uint8([[bgr]] ), cv2.COLOR_BGR2YCrCb)[0][0]minYCB = np.array([ycb[0] - thresh, ycb[1] - thresh, ycb[2] - thresh])
maxYCB = np.array([ycb[0] + thresh, ycb[1] + thresh, ycb[2] + thresh])maskYCB = cv2.inRange(brightYCB, minYCB, maxYCB)
resultYCB = cv2.bitwise_and(brightYCB, brightYCB, mask = maskYCB)#convert 1D array to 3D, then convert it to LAB and take the first element
lab = cv2.cvtColor( np.uint8([[bgr]] ), cv2.COLOR_BGR2LAB)[0][0]minLAB = np.array([lab[0] - thresh, lab[1] - thresh, lab[2] - thresh])
maxLAB = np.array([lab[0] + thresh, lab[1] + thresh, lab[2] + thresh])maskLAB = cv2.inRange(brightLAB, minLAB, maxLAB)
resultLAB = cv2.bitwise_and(brightLAB, brightLAB, mask = maskLAB)cv2.imshow("Result BGR", resultBGR)
cv2.imshow("Result HSV", resultHSV)
cv2.imshow("Result YCB", resultYCB)
cv2.imshow("Output LAB", resultLAB)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++

//C++ code
cv::Vec3b bgrPixel(255, 50, 50);
// Create Mat object from vector since cvtColor accepts a Mat object
Mat3b bgr (bgrPixel);//Convert pixel values to other color spaces.
Mat3b hsv,ycb,lab;
cvtColor(bgr, ycb, COLOR_BGR2YCrCb);
cvtColor(bgr, hsv, COLOR_BGR2HSV);
cvtColor(bgr, lab, COLOR_BGR2Lab);
//Get back the vector from Mat
Vec3b hsvPixel(hsv.at(0,0));
Vec3b ycbPixel(ycb.at(0,0));
Vec3b labPixel(lab.at(0,0));int thresh = 50;cv::Scalar minBGR = cv::Scalar(bgrPixel.val[0] - thresh, bgrPixel.val[1] - thresh, bgrPixel.val[2] - thresh)
cv::Scalar maxBGR = cv::Scalar(bgrPixel.val[0] + thresh, bgrPixel.val[1] + thresh, bgrPixel.val[2] + thresh) cv::Mat maskBGR, resultBGR;
cv::inRange(bright, minBGR, maxBGR, maskBGR);
cv::bitwise_and(bright, bright, resultBGR, maskBGR);cv::Scalar minHSV = cv::Scalar(hsvPixel.val[0] - thresh, hsvPixel.val[1] - thresh, hsvPixel.val[2] - thresh)
cv::Scalar maxHSV = cv::Scalar(hsvPixel.val[0] + thresh, hsvPixel.val[1] + thresh, hsvPixel.val[2] + thresh) cv::Mat maskHSV, resultHSV;
cv::inRange(brightHSV, minHSV, maxHSV, maskHSV);
cv::bitwise_and(brightHSV, brightHSV, resultHSV, maskHSV);cv::Scalar minYCB = cv::Scalar(ycbPixel.val[0] - thresh, ycbPixel.val[1] - thresh, ycbPixel.val[2] - thresh)
cv::Scalar maxYCB = cv::Scalar(ycbPixel.val[0] + thresh, ycbPixel.val[1] + thresh, ycbPixel.val[2] + thresh) cv::Mat maskYCB, resultYCB;
cv::inRange(brightYCB, minYCB, maxYCB, maskYCB);
cv::bitwise_and(brightYCB, brightYCB, resultYCB, maskYCB);cv::Scalar minLAB = cv::Scalar(labPixel.val[0] - thresh, labPixel.val[1] - thresh, labPixel.val[2] - thresh)
cv::Scalar maxLAB = cv::Scalar(labPixel.val[0] + thresh, labPixel.val[1] + thresh, labPixel.val[2] + thresh) cv::Mat maskLAB, resultLAB;
cv::inRange(brightLAB, minLAB, maxLAB, maskLAB);
cv::bitwise_and(brightLAB, brightLAB, resultLAB, maskLAB);cv2::imshow("Result BGR", resultBGR)
cv2::imshow("Result HSV", resultHSV)
cv2::imshow("Result YCB", resultYCB)
cv2::imshow("Output LAB", resultLAB)

在这里插入图片描述

我们也可以设计一个GUI,通过人工调节颜色的范围来观察图像中的变化,获取想要的 颜色

python代码如下:

import cv2
import numpy as np
import os#定义HSV滑块的值
def empty(a):h_min = cv2.getTrackbarPos("Hue Min","TrackBars")h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")v_min = cv2.getTrackbarPos("Val Min", "TrackBars")v_max = cv2.getTrackbarPos("Val Max", "TrackBars")print(h_min, h_max, s_min, s_max, v_min, v_max)return h_min, h_max, s_min, s_max, v_min, v_max#图片拼接,将4张图片拼接到一起
def stackImages(scale,imgArray):rows = len(imgArray)cols = len(imgArray[0])rowsAvailable = isinstance(imgArray[0], list)width = imgArray[0][0].shape[1]height = imgArray[0][0].shape[0]if rowsAvailable:for x in range ( 0, rows):for y in range(0, cols):if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)else:imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)imageBlank = np.zeros((height, width, 3), np.uint8)hor = [imageBlank]*rowshor_con = [imageBlank]*rowsfor x in range(0, rows):hor[x] = np.hstack(imgArray[x])ver = np.vstack(hor)else:for x in range(0, rows):if imgArray[x].shape[:2] == imgArray[0].shape[:2]:imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)else:imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)hor= np.hstack(imgArray)ver = horreturn verroot = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
path = os.path.join(root,'data/cube.jpg')
cv2.namedWindow("TrackBars")
# 创建一个窗口,放置6个滑动条rackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",19,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",110,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",240,255,empty)
cv2.createTrackbar("Val Min","TrackBars",153,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)while True:img = cv2.imread(path)imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)# 调用回调函数,获取滑动条的值h_min = cv2.getTrackbarPos("Hue Min","TrackBars")h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")v_min = cv2.getTrackbarPos("Val Min", "TrackBars")v_max = cv2.getTrackbarPos("Val Max", "TrackBars")h_min, h_max, s_min, s_max, v_min, v_max = empty(0)lower = np.array([h_min,s_min,v_min])upper = np.array([h_max,s_max,v_max])# 获得指定颜色范围内的掩码mask = cv2.inRange(imgHSV,lower,upper)# 对原图图像进行按位与的操作,掩码区域保留imgResult = cv2.bitwise_and(img,img,mask=mask)# cv2.imshow("Original",img)# cv2.imshow("HSV",imgHSV)# cv2.imshow("Mask", mask)# cv2.imshow("Result", imgResult)imgStack = stackImages(0.6,([img,imgHSV],[mask,imgResult]))cv2.imshow("Stacked Images", imgStack)cv2.waitKey(1)

在这里插入图片描述

相关内容

热门资讯

安卓系统的如何测试软件,从入门... 你有没有想过,你的安卓手机里那些神奇的软件是怎么诞生的呢?它们可不是凭空出现的,而是经过一系列严格的...
小米8安卓系统版本,安卓系统版... 你有没有发现,手机更新换代的速度简直就像坐上了火箭呢?这不,小米8这款手机自从上市以来,就凭借着出色...
华为手机安卓系统7以上,创新体... 你有没有发现,最近华为手机越来越受欢迎了呢?尤其是那些搭载了安卓系统7.0及以上版本的机型,简直让人...
儿童英语免费安卓系统,儿童英语... 哇,亲爱的家长朋友们,你是否在为孩子的英语学习发愁呢?别担心,今天我要给你带来一个超级好消息——儿童...
ios系统切换安卓系统还原,还... 你有没有想过,有一天你的手机从iOS系统切换到了安卓系统,然后再从安卓系统回到iOS系统呢?这听起来...
灵焕3装安卓系统,引领智能新体... 你知道吗?最近手机圈里可是掀起了一股热潮,那就是灵焕3这款神器的安卓系统升级。没错,就是那个曾经以独...
安卓系统指南针软件,探索未知世... 手机里的指南针功能是不是让你在户外探险时倍感神奇?但你知道吗,安卓系统中的指南针软件可是大有学问呢!...
华为是不用安卓系统了吗,迈向自... 最近有个大新闻在科技圈里炸开了锅,那就是华为是不是不再使用安卓系统了?这可不是一个简单的问题,它涉及...
安卓系统热点开启失败,排查与解... 最近是不是你也遇到了安卓系统热点开启失败的小麻烦?别急,让我来给你详细说说这个让人头疼的问题,说不定...
小米max2系统安卓,安卓系统... 你有没有听说过小米Max2这款手机?它那超大的屏幕,简直就像是个移动的电脑屏幕,看视频、玩游戏,那叫...
电池健康怎么保持安卓系统,优化... 手机可是我们生活中不可或缺的好伙伴,而电池健康度就是它的生命力。你有没有发现,随着使用时间的增长,你...
安卓手机怎么调系统颜色,安卓手... 你有没有发现,你的安卓手机屏幕颜色突然变得不那么顺眼了?是不是也想给它换换“脸色”,让它看起来更有个...
安卓系统清粉哪个好,哪款清粉工... 手机用久了,是不是觉得卡得要命?别急,今天就来聊聊安卓系统清理垃圾哪个软件好。市面上清理工具那么多,...
华为被限制用安卓系统,挑战安卓... 你知道吗?最近科技圈可是炸开了锅!华为,这个我们耳熟能详的名字,竟然因为一些“小插曲”被限制了使用安...
安卓系统是不是外国,源自外国的... 你有没有想过,我们每天离不开的安卓系统,它是不是外国货呢?这个问题听起来可能有点奇怪,但确实很多人都...
安卓系统缺少文件下载,全面解析... 你有没有发现,用安卓手机的时候,有时候下载个文件真是让人头疼呢?别急,今天就来聊聊这个让人烦恼的小问...
kktv系统刷安卓系统怎么样,... 你有没有听说最近KKTV系统刷安卓系统的事情?这可是个热门话题呢!咱们一起来聊聊,看看这个新玩意儿到...
安卓系统连接电脑蓝牙,操作指南... 你有没有遇到过这种情况:手机里堆满了各种好用的应用,可就是想找个方便快捷的方式,把手机里的音乐、照片...
安卓车机11.0系统包,智能驾... 你有没有发现,最近你的安卓车机系统好像悄悄升级了呢?没错,就是那个安卓车机11.0系统包!这可不是一...
安卓系统最高到多少,从初代到最... 你有没有想过,你的安卓手机系统升级到哪一步了呢?是不是好奇安卓系统最高能到多少呢?别急,今天就来带你...