目錄

廣告 AD

OpenCV:擷取顏色的技巧,抓出想要的顏色!

- OpenCV

有時候靠著 Image Processing 就可以解決的問題

就不用勞煩 AI 出手啦

這次要講的是擷取特定顏色的方法

廣告 AD

擷取顏色在辨識某樣物品或文字的時候很好用

可以把該樣物品對應的顏色範圍都擷取出來,後續再做處理


原圖

成果圖


首先我們讀取圖片並使用 cv2.cvtColor 把讀取進來的圖片轉成 HSV 格式

因為 HSV 格式能更好地擷取我們想要的顏色

Python

img = cv2.imread('test.jpg')
cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

再來設定好想要的顏色範圍

python

hsv_color1 = np.asarray([20, 100, 50])   # 深橘色
hsv_color2 = np.asarray([40, 255, 255])   # 亮綠色

並使用 cv2.inRange 擷取我們設定好的顏色範圍

Python

cv2.inRange(img_hsv, hsv_color1, hsv_color2)

下圖就是我們抓到的範圍


白色為擷取到的部分


有了遮罩後,使用 cv2.bitwise_and 依照遮罩拿取我們原圖的資料

先是 imgimg 做 AND,再依照遮罩拿取

由於自己和自己做 AND 一樣是自己,所以就只有依照遮罩拿取

Python

cv2.bitwise_and(img, img, mask=mask)

最後使用 cv2.cvtColor 轉成 matplotlib 使用的 RGB 格式

Python

cv2.cvtColor(result, cv2.COLOR_BGR2RGB)

這邊為全部程式碼:

python

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('test.jpg')
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  # 將圖片從 BGR 格式轉成 HSV 格式

hsv_color1 = np.asarray([20, 100, 50])   # 深橘色
hsv_color2 = np.asarray([40, 255, 255])   # 亮綠色

mask = cv2.inRange(img_hsv, hsv_color1, hsv_color2)  # 擷取顏色
result = cv2.bitwise_and(img, img, mask=mask)  # 將原圖套用遮罩
result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)  # 轉換格式至 RGB

plt.imshow(result_rgb)  # 設定顯示圖片
plt.axis('off')  # 關閉顯示座標軸
plt.show()  # 顯示擷取的部分

知道了如何提取顏色,但到底我想要的顏色對應的 HSV 又是多少呢?

下面我們就把 HSV 所有的數值都印出來

來看看到底每個數值對應到的顏色是甚麼吧 ~


我們輸入的圖一共有 2 種格式:

分別為 uint8 的整數格式和 float32 的浮點數格式

兩者 HSV 的範圍有點不一樣

因為 uint8 的範圍大小最多到 255,裝不下色相的 360

因此 / 2 變成 0 ~ 179

uint8:

  • H: 0 ~ 179
  • S: 0 ~ 255
  • V: 0 ~ 255

float32:

  • H: 0 ~ 359
  • S: 0.0 ~ 1.0
  • V: 0.0 ~ 1.0

下面我們就使用 2D 圖片把數值印出來,並附上印出來的程式碼

分別為:

  • 色相 vs 飽和度
  • 色相 vs 亮度

Uint8 格式 (X軸: 色相,Y軸: 飽和度)

Uint8 格式 (X軸: 色相,Y軸: 飽和度)

Float32 格式 (X軸: 色相,Y軸: 飽和度)

Float32 格式 (X軸: 色相,Y軸: 飽和度)

python

import matplotlib.pyplot as plt
import numpy as np
import cv2

shape = (256, 180, 3)
img = np.zeros(shape, dtype=np.uint8)
for i in range(180):
  for j in range(256):
    img[j,i] = [i, j, 255] 
img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)

plt.imshow(img)
plt.xlabel('Hue')
plt.ylabel('Saturation')
plt.title('Value = 255')
plt.show()

Uint8 格式 (X軸: 色相,Y軸: 亮度)

Uint8 格式 (X軸: 色相,Y軸: 亮度)

Float32 格式 (X軸: 色相,Y軸: 亮度)

Float32 格式 (X軸: 色相,Y軸: 亮度)

python

import matplotlib.pyplot as plt
import numpy as np
import cv2

shape = (256, 180, 3)
img = np.zeros(shape, dtype=np.uint8)
for i in range(180):
  for j in range(256):
    img[j,i] = [i, 255, j] 
img = cv2.cvtColor(img, cv2.COLOR_HSV2RGB)

plt.imshow(img)
plt.xlabel('Hue')
plt.ylabel('Value')
plt.title('Saturation = 255')
plt.show()

廣告 AD