图片颜色识别
- 1. RGB颜色空间
- 2. 颜色加法
- 2.1使用numpy对图像进行加法
- 2.2使用opencv加法(cv2.add)
- 3 颜色加权加法(cv2.addWeighted())
- 4. HSV颜色空间
- 5. 制作掩膜
- 4. 与运算(cv2.bitwise_and)
- 5.颜色的替换
- 7 ROI切割
在本实验中,主要是通过掩膜对原图像进行与运算来找到我们要识别的颜色,因此我们需要了解如何在一张图片中寻找目标颜色、掩膜是什么以及与运算的概念,下面一一介绍。
1. RGB颜色空间
在图像处理中,最常见的就是RGB颜色空间。RGB颜色空间是我们接触最多的颜色空间,是一种用于表示和显示彩色图像的一种颜色模型。RGB代表红色(Red)、绿色(Green)和蓝色(Blue),这三种颜色通过不同强度的光的组合来创建其他颜色,广泛应用于我们的生活中,比如电视、电脑显示屏以及上面实验中所介绍的RGB彩色图。
RGB颜色模型基于笛卡尔坐标系,如下图所示,RGB原色值位于3个角上,二次色青色、红色和黄色位于另外三个角上,黑色位于原点处,白色位于离原点最远的角上。因为黑色在RGB三通道中表现为(0,0,0),所以映射到这里就是原点;而白色是(255,255,255),所以映射到这里就是三个坐标为最大值的点。
RGB颜色空间可以产生大约1600万种颜色,几乎包括了世界上的所有颜色,也就是说可以使用RGB颜色空间来生成任意一种颜色。
注意:
- 在OpenCV中,颜色是以BGR的方式进行存储的,而不是RGB,这也是上面红色的像素值是(0,0,255)而不是(255,0,0)的原因。
2. 颜色加法
你可以使用OpenCV的cv.add()函数把两幅图像相加,或者可以简单地通过numpy操作添加两个图像,如res = img1 + img2。两个图像应该具有相同的大小和类型。
OpenCV加法和Numpy加法之间存在差异。OpenCV的加法是饱和操作,而Numpy添加是模运算
2.1使用numpy对图像进行加法
图片加上数字代码如下:
'''颜色的加法运算——使用numpy进行'''img=cv2.imread(r'../15day4.10/src/flower.png')print(img[350,340:350,:])img2=img+100print(img2[350,340:350,:])'''[[245 240 236][245 240 237][245 240 237][245 241 236][246 243 235][242 241 235][235 235 236][198 199 210][155 154 181][107 101 146]][[ 89 84 80][ 89 84 81][ 89 84 81][ 89 85 80][ 90 87 79][ 86 85 79][ 79 79 80][ 42 43 54][255 254 25][207 201 246]]'''# 由数组可以看出,因为uint8类型的数据最大值为255所以直接进行numpy的加法运算,两个元素相加超过255就会自动用这个和%256cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.waitKey(0)
图片加上图片的代码如下:
'''颜色的加法运算——使用numpy进行图片加图片'''img=cv2.imread(r'../15day4.10/src/cao.png')img2=cv2.imread(r'../15day4.10/src/pig.png')img3=img+img2# 由数组可以看出,因为uint8类型的数据最大值为255所以直接进行numpy的加法运算,两个元素相加超过255就会自动用这个和%256cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.imshow('img3',img3)cv2.waitKey(0)
注意:
- 由上面代码数组数组可以看出,因为uint8类型的数据最大值为255所以直接进行numpy的加法运算,两个元素相加超过255就会自动用这个和%256
- 一张图片中的像素点加上一个值就表示改变这个像素点的颜色
- 一张图片加上另外一张图片也可以
2.2使用opencv加法(cv2.add)
代码如下:
'''颜色的加法运算——使用cv2.add进行图片加数字'''img=cv2.imread(r'../15day4.10/src/flower.png')print(img[350,340:350,:])img2=cv2.add(img,100)print(img2[350,340:350,:])'''
[[245 240 236][245 240 237][245 240 237][245 241 236][246 243 235][242 241 235][235 235 236][198 199 210][155 154 181][107 101 146]]
[[255 255 255][255 255 255][255 255 255][255 255 255][255 255 255][255 255 255][255 255 255][255 255 255][255 254 255][207 201 246]]'''cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.waitKey(0)
图片加图片代码如下:
'''颜色的加法运算——使用cv2.add进行图片加图片'''img=cv2.imread(r'../15day4.10/src/cao.png')img2=cv2.imread(r'../15day4.10/src/pig.png')img3=cv2.add(img,img2)cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.imshow('img3',img3)cv2.waitKey(0)
注意:
- 使用open的加法(cv2.add())函数时如果某个像素点数的BGR值与一个值相加超过255时,只会使这个BRG为255
3 颜色加权加法(cv2.addWeighted())
这其实也是加法,但是不同的是两幅图像的权重不同,这就会给人一种混合或者透明的感觉。图像混合的计算公式如下:
g(x) = (1−α)f0(x) + αf1(x)
通过修改 α 的值(0 → 1),可以实现非常炫酷的混合。
现在我们把两幅图混合在一起。第一幅图的权重是0.7,第二幅图的权重是0.3。函数cv2.addWeighted()可以按下面的公式对图片进行混合操作。
dst = α⋅img1 + β⋅img2 + γ
这里γ取为零。
格式;
cv2.addWeighted(image1,a,image2,b,γ) #a是img1的权重,b是img2的权重
代码如下:
'''颜色的加权加法'''img=cv2.imread(r'../15day4.10/src/cao.png')img2=cv2.imread(r'../15day4.10/src/pig.png')img3=cv2.addWeighted(img,0.3,img2,0.6,0)cv2.imshow('img',img)cv2.imshow('img2',img2)cv2.imshow('img3',img3)cv2.waitKey(0)
注意:
- 两个图片的权重不必加起来等于1
4. HSV颜色空间
HSV颜色空间指的是HSV颜色模型,这是一种与RGB颜色模型并列的颜色空间表示法。RGB颜色模型使用红、绿、蓝三原色的强度来表示颜色,是一种加色法模型,即颜色的混合是添加三原色的强度。而HSV颜色空间使用 色调(Hue)、饱和度(Saturation)和亮度(Value) 三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低。
HSV颜色模型是一种六角锥体模型,如下图所示:
HSV的具体描述
此处把部分红色归为紫色范围:
代码如下:
'''HSV'''img=cv2.imread(r'../15day4.10/src/demo.png')img_hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)cv2.imshow('img',img)cv2.imshow('img_hsv',img_hsv)cv2.waitKey(0)
注意:
- 在opencv中读取出来的图像的颜色都是BGR,要用cv2.cvtColor()进行转换
5. 制作掩膜
掩膜(Mask)是一种在图像处理中常见的操作,它用于选择性地遮挡图像的某些部分,以实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图像的大小相同,其中目标区域被设置为1(或白色),而其他区域被设置为0(或黑色),并且目标区域可以根据HSV的颜色范围进行修改,如下图就是制作红色掩膜的过程:
通过这个掩膜,我们就可以对掩膜中的白色区域所对应的原图中的区域进行处理与操作。
代码格式:
cv2.inRange(img_hsv,lower,upper)
参数说明:
- img_hsv:就是bgr转为hsv的图
- lower:H,S,V三种元素对应颜色的最小值
- upper:H,S,V三种元素对应颜色的最大值
代码如下:
img=cv2.imread(r'../15day4.10/src/demo.png')img_hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)#红色的最小hsv的值lower=np.array([0,43,46])#红色的最大hsv的值upper=np.array([10,255,255])img_mask=cv2.inRange(img_hsv,lower,upper)cv2.imshow('img',img)cv2.imshow('img_mask',img_mask)cv2.waitKey(0)
掩膜是为了得到想要图像的部分
4. 与运算(cv2.bitwise_and)
我们在高中时学过逻辑运算中的“与”运算,其规则是当两个命题都是真时,其结果才为真。而在图像处理中,“与”运算被用来对图像的像素值进行操作。具体来说,**就是将两个图像中所有的对应像素值一一进行“与”运算,**从而得到新的图像。从上面的图片我们可以看出,掩膜中有很多地方是黑色的,其像素值为0,那么在与原图像进行“与”运算的时候,得到的新图像的对应位置也是黑色的,如下图所示:
代码格式:
color_image_np = cv2.bitwise_and(image_np, image_np, mask=mask_image_np)
参数说明:
- image_np:原始BGR的图像
- mask_image_np:进行掩膜运算后的图像
注意:
- 参数一image_np和参数二image_np 的每一位像素进行按位与操作 由于是同一张图片 因此相同像素按位与后还是当前像素
- 因为掩膜运算得到的是想要的图像为白色(255),其余为黑色(0),进行and时掩膜运算后的图像 在前面,后面原图像不想要操作部分不会进行按位与运算(0 and 表达式)=0,表达式不执行
具体代码如下:
'''按位与运算'''img=cv2.imread(r'../15day4.10/src/demo.png')img_hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)#红色的最小hsv的值lower=np.array([0,43,46])#红色的最大hsv的值upper=np.array([10,255,255])#进行掩膜运算img_mask=cv2.inRange(img_hsv,lower,upper)#进行按位与运算img_bit=cv2.bitwise_and(img,img,mask=img_mask)cv2.imshow('img',img)cv2.imshow('img_bit',img_bit)cv2.waitKey(0)
5.颜色的替换
由于掩膜与原图的大小相同,并且像素位置一一对应,那么我们就可以得到掩膜中白色(也就是像素值为255)区域的坐标,并将其带入到原图像中,即可得到原图中的红色区域的坐标,然后就可以修改像素值了,这样就完成了颜色的替换,如下图所示:
将上图的红色圆替换成蓝色
'''颜色替换'''# 现将原图变为hsv的图像img=cv2.imread(r'../15day4.10/src/demo.png') img_hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)# 求红色的掩膜# 求红色的hsv的最小值lower=np.array([0,43,46])# 求红色的hsv的最大值upper=np.array([10,255,255])cv2.imshow('img',img)#进行掩膜运算img_mask=cv2.inRange(img_hsv,lower,upper)img[img_mask==255]=[255,0,0]cv2.imshow('img',img)cv2.waitKey(0)
步骤:
- 1.先对原图变为hsv格式
- 2.求想要替换图像的颜色hsv的最大值和最小值
- 3.对其做掩膜运算
- 4.对原图掩膜运算的结果等于255区域改变BGR
7 ROI切割
ROI:Region of Interest,翻译过来就是感兴趣的区域。什么意思呢?比如对于一个人的照片,假如我们要检测眼睛,因为眼睛肯定在脸上,所以我们感兴趣的只有脸这部分,其他都不care,所以可以单独把脸截取出来,这样就可以大大节省计算量,提高运行速度。
还记得Numpy这个库吗?我们在使用OpenCV进行读取图像时,图像数据会被存储为Numpy数组,这也意味着我们可以使用Numpy数组的一些操作来对图像数据进行处理,比如切片。而本实验的原理也**是基于Numpy数组的切片操作来完成的,**因此在对应的组件中就需要填我们要切割的ROI区域的坐标来完成ROI切割操作。
注意:在OpenCV中,坐标的x轴的正方向是水平向右,y轴的正方向是垂直向下,与数学上的二维坐标并不相同。
在计算机视觉中,当我们使用OpenCV读取RGB三通道图像时,它会被转换成一个三维的Numpy数组。这个数组里的每个元素值都表示图像的一个像素值。这个三维数组的第一个维度(即轴0)通常代表图像的高度,第二个维度(即轴1)代表图像的宽度,而第三个维度(即轴2)代表图像的三个颜色通道(B、G、R,OpenCV读取到的图像以BGR的方式存储)所对应的像素值。
因此,我们可以通过指定切片的范围来选择特定的高度和宽度区域。这样,我们就能够获取这个区域内的所有像素值,即得到了这个区域的图像块,通过Numpy的切片操作,**我们就完成了ROI切割的操作。这种提取ROI的方法允许我们仅获取感兴趣区域内的像素,**而忽略其他不相关的部分,从而大大减少数据处理和存储的负担。
代码如下:
'''ROI切割'''img=cv2.imread(r'../15day4.10/src/1.jpg') img2=img[100:500,200:700]cv2.imshow('img',img)cv2.imshow("img2",img2)cv2.waitKey(0)