为了标准化起见,国际照明委员会(CIE)规定用波长为700nm、546.1nm、435.8nm的单色光分别作为红(R)、绿(G)、蓝(B)三原色。红绿蓝三原色按照比例混合可以得到各种颜色,其配色方程为︰C=aR+bG+cB
图1 RGB颜色空间坐标系
HSI(Hue-Saturation-Intensity , HSI)模型用H、S、I三参数描述颜色特性。
图2 HSI颜色空间
给定一幅RGB颜色空间格式的图像,将图像的R分量、G分量、B分量分别归一化。在RGB颜色空间中,位于(x,y)空间位置的像素点的颜色用该像素点的R分量R(x,y)、G分量G(x,y)和B分量B(x,y)三个数值表示。在HSI颜色空间中,位于空间位置的像素点的H分量H(x,y)、S分量S(x,y)、I分量I(x,y)可分别由以下公式计算得到:
(1)当H(x,y)∈ [00,1200)时转换公式为:
(2)当H(x,y)∈ [1200,2400)时转换公式为:
(3)当H(x,y)∈ [2400,3600)时转换公式为:
对于彩色图像的直方图均衡化,首先需利用HSI函数将图像转换至HSI颜色空间,再利用设计的RGB函数将图像从HSI颜色空间转换至RGB颜色空间进行显示。最终,对彩色图像进行图像切割、检测操作,比如切割苹果、检测火焰等,根据测试效果。
RGB转HIS函数;
1 #RGB转HSI颜色空间
2 def HSI(self,img):
3 r = img[:,:,0].astype(np.float32)
4 g = img[:,:,1].astype(np.float32)
5 b = img[:,:,2].astype(np.float32)
6
7 I = (r+g+b)/3
8 I = I/255
9 img_min = np.min(img,axis=-1)
10 S = 1 - (3/(r+g+b)*img_min)
11 a = 0.5*((r-g)+(r-b))
12 botton = ((r-g)**2+((r-b)*(g-b))+ sys.float_info.min)**0.5
13 den =a /botton
14 den[den>1]=1
15 den[den<-1]=-1
16 H = np.arccos(den)
17 index = np.where(g<b)
18 H[index]= 2*m.pi-H[index]
19 H /= 2 * m.pi
20 H[S == 0] = 0
21
22 hsi = np.zeros([img.shape[0],img.shape[1],img.shape[2]],dtype=np.float32)
23 hsi[:,:,0] = H
24 hsi[:,:,1] = S
25 hsi[:,:,2] = I
26 return hsi
HIS转RGB函数;
1 #HSI转RGB颜色空间
2 def RGB(self,hsi):
3 #rgb
4 H = hsi[:,:,0]
5 S = hsi[:,:,1]
6 I = hsi[:,:,2]
7 H *=2*m.pi
8
9 rgb = np.zeros(hsi.shape,np.uint8)
10 R = np.zeros(H.shape, dtype=np.float32)
11 G = np.zeros(H.shape, dtype=np.float32)
12 B = np.zeros(H.shape, dtype=np.float32)
13
14 index = np.where((H>=0)&(H<2*m.pi/3))
15 R[index] = I[index] * (1+(S[index]*np.cos(H[index]))/(np.cos(m.pi/3-H[index])))
16 B[index] = I[index]*(1-S[index])
17 G[index] = 3*I[index]-(B[index]+R[index])
18
19 index = np.where((H>=2*m.pi/3)&(H<4*m.pi/3))
20 R[index] = I[index]*(1-S[index])
21 G[index] = I[index] * (1+(S[index]*np.cos(H[index]-2*m.pi/3))/(np.cos(m.pi-H[index])))
22 B[index] = 3*I[index]-(R[index]+G[index])
23
24 index = np.where((H>=4*m.pi/3)&(H<2*m.pi))
25 B[index] = I[index] * (1+(S[index]*np.cos(H[index]-4*m.pi/3))/(np.cos(5*m.pi/3-H[index])))
26 G[index] = I[index]*(1-S[index])
27 R[index] = 3*I[index]-(G[index]+B[index])
28
29 rgb[:,:,0] = (255*R).astype(np.uint8)
30 rgb[:,:,1] = (255*G).astype(np.uint8)
31 rgb[:,:,2] = (255*B).astype(np.uint8)
32 return rgb
对苹果进行切割;
1 #苹果检测
2 def appleDetect(self,img):
3 # img = img.astype(np.float32)
4 r = img[:,:,0]
5 g = img[:,:,1]
6 b = img[:,:,2]
7 hsi = self.HSI(img)
8 H = hsi[:,:,0]
9 H *=2*m.pi
10 print(img.shape)
11 apple = np.zeros(img.shape,dtype=np.uint32)
12 detect_ground = np.where(((H>=0)&(H<=m.pi/3.6))|((H>m.pi*1.3)&(H<=2*m.pi)))
13 apple[:,:,0][detect_ground] = r[detect_ground]
14 apple[:,:,1][detect_ground] = g[detect_ground]
15 apple[:,:,2][detect_ground] = b[detect_ground]
16 apple = apple.astype(np.uint8)
17 cv.imshow("apple_img",apple)
对火焰进行检测;
1 #火焰检测
2 def fireDetect(self,img):
3
4 r = img[:,:,0]
5 g = img[:,:,1]
6 b = img[:,:,2]
7 hsi = self.HSI(img)
8 H = hsi[:,:,0]
9 S = hsi[:,:,1]
10 I = hsi[:,:,2]
11 S *= 100
12 I *= 255
13 H *=2*m.pi
14 # rgb = self.RGB(hsi)
15 detect_ground = np.where((H >= 2*m.pi/3) & (H< 2 * m.pi) & (S >= 20 )& (I >=100))
16 fire = np.zeros(img.shape,dtype=np.uint32)
17 # print(detect_ground)
18 fire[:,:,0][detect_ground] = r[detect_ground]
19 fire[:,:,1][detect_ground] = g[detect_ground]
20 fire[:,:,2][detect_ground] = b[detect_ground]
21 # print(fire)
22 fire = fire.astype(np.uint8)
23 cv.imshow("fire",fire)
图像显示;
1 #图像显示
2 def main(self):
3 img_apple = cv.imread("./data/images/apple.jpg")
4 img_fire = cv.imread("./data/images/fire.jpg")
5 hsi = self.HSI(img_apple)
6 rgb = self.RGB(hsi)
7 self.appleDetect(img_apple)
8 self.fireDetect(img_fire)
9 cv.imshow("orgin_apple",img_apple)
10 # cv.imshow("I",I)
11 # cv.imshow("S",S)
12 # cv.imshow("H",H)
13 cv.imshow("hsi",hsi)
14 cv.imshow("hsi_to_rgb_img",rgb)
程序执行;
1 if __name__=="__main__":
2 PicDetect().main()
3 k = cv.waitKey(0)&0xFF
4 if k == 27:
5 cv.destroyAllWindows()
6