圖片顏色識別
- 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)