OpenCV—python 顏色空間(RGB,HSV,Lab)與 顏色直方圖

一、圖像分類的過(guò)程

image.png
  1. 圖片必須經(jīng)過(guò)標(biāo)注
    圖片的類別為有限的集合,如{貓、狗、牛、馬、狼}
    每個(gè)類別的圖片數(shù)量接近,如果不同類別圖片的數(shù)量差異很大,訓(xùn)練出來(lái)的分類器容易傾向于圖片數(shù)量多的類別

  2. 劃分訓(xùn)練/測(cè)試集
    在訓(xùn)練之前,要把數(shù)據(jù)集劃分為訓(xùn)練集(學(xué)習(xí)分類器)和測(cè)試集(對(duì)分類器進(jìn)行評(píng)估)
    訓(xùn)練集和測(cè)試集相互獨(dú)立,不重合!

3.特征表示 :對(duì)圖片進(jìn)行數(shù)值處理,轉(zhuǎn)換成計(jì)算機(jī)可理解的特征,常用特征:

  • 顏色直方圖(Color Histograms)
  • 方向梯度直方圖(Histogram of Oriented Gradients,HOG)
  • 局部二值模式(Local Binary Pattern,LBP)
  1. 分類算法 :一般分類算法即可:邏輯回歸,支持向量機(jī)(SVM),隨機(jī)森林

  2. 模型評(píng)估 : 混淆矩陣(Confusion Matrix)

  • 精確度(Precision)
  • 召回率(Recall)
  • F1值(F1 score) recall與Precision的調(diào)和均值

二、開(kāi)發(fā)環(huán)境:(安裝)OpenCV 計(jì)算機(jī)視覺(jué)庫(kù)

安裝:
方法1:conda install -c menpo opencv 
方法2:conda install --channel https://conda.anaconda.org/menpo opencv3 
方法3:pip/conda install opencv-python
方法4:使用 whl 文件進(jìn)行安裝,進(jìn)入網(wǎng)站 http://www.lfd.uci.edu/~gohlke/pythonlibs/。 
      下載與當(dāng)前環(huán)境兼容的 opencv 文件。切換到該文件所在的目錄,在命令行環(huán)境下使用 
      例如:安裝文件:opencv_python-3.2.0-cp35-cp35m-win_amd64.whl
      pip install opencv_python-3.2.0-cp35-cp35m-win_amd64.whl

opencv 的導(dǎo)入: 
import cv2
cv2.__version__
    
    OpenCV的使用
        在線文檔:http://docs.opencv.org/2.4.11/

三、顏色空間(顏色模型:RGB,HSV,Lab)

RGB顏色空間有:
RGB :模型容易理解,連續(xù)變換顏色時(shí)不直觀
(紅red 綠green 藍(lán)blue)三原色:取值范圍都是:[0,255],[0,255],[0,255]

HSV: 是為了數(shù)字化圖像提出來(lái)了,不能很好的表示人眼解釋圖像過(guò)程

  • H (Hue)色相:[0,360]
  • S (Saturation)飽和度,即色彩純凈度,0飽和度為白色
  • V (Value/Brightness):明度 0明度為純黑色

在OpenCV中,顏色范圍:

  • H = [0,179]
  • S = [0,255]
  • V = [0,255]

Lab:顏色之間的歐式距離有具體含義–距離越大,人眼感官兩種顏色差距越遠(yuǎn)

  • L 通道:像素亮度,上白下黑 中間灰
  • a 通道:左綠 右紅
  • b 通道:一端純藍(lán),一端純黃

灰度圖:每個(gè)像素[0,255]
根據(jù)人眼敏感度,把RGB圖片轉(zhuǎn)換為灰度圖,不是簡(jiǎn)單把RGB每個(gè)通道取平均值
而是:Y = 0.299R + 0.587G + 0.114*B

image.png

3.1 opencv–HSV顏色空間

HSV(hue,saturation,value)顏色空間的模型對(duì)應(yīng)于圓柱坐標(biāo)系中的一個(gè)圓錐形子集,圓錐的頂面對(duì)應(yīng)于V=1. 它包含RGB模型中的R=1,G=1,B=1 三個(gè)面,所代表的顏色較亮。
色彩H由繞V軸的旋轉(zhuǎn)角給定。紅色對(duì)應(yīng)于 角度0° ,綠色對(duì)應(yīng)于角度120°,藍(lán)色對(duì)應(yīng)于角度240°。

在HSV顏色模型中,每一種顏色和它的補(bǔ)色相差180° 。 飽和度S取值從0到1,所以圓錐頂面的半徑為1。
在圓錐的頂點(diǎn)(即原點(diǎn))處V=0,H和S無(wú)定義, 代表黑色。
圓錐的頂面中心處 S=0,V=1,H無(wú)定義,代表白色。
從該點(diǎn)到原點(diǎn)代表亮度漸暗的灰色,即具有不同 灰度的灰色。
對(duì)于這些點(diǎn),S=0,H的值無(wú)定義。可以說(shuō),HSV模型中的V軸對(duì)應(yīng)于RGB顏色空間中的主對(duì)角線。 在圓錐頂面的圓周上的顏色,V=1,S=1,這種顏色是純色。

HSV顏色空間它錐形的鉆換模型中可以理解到: hue 通道的取值范圍就應(yīng)該是 0-360度,單數(shù)在opencv中其取值范圍 [0,180]。


image.png

在opencv-hsv取值詳情如下:


image.png

顏色庫(kù):


image.png

image.png

原本輸出的 HSV 的取值范圍分別是 0-360, 0-1, 0-1;但是為了匹配目標(biāo)數(shù)據(jù)類型 OpenCV 將每個(gè)通道的取值范圍都做了修改,于是就變成了 0-180, 0-255, 0-255,并且同時(shí)解釋道:為了適應(yīng) 8bit 0-255 的取值范圍,將 hue 通道 0-360 的取值范圍做了減半處理

四、OpenCV處理圖片

4.1 直接讀取圖片

import cv2                      #導(dǎo)入 Opencv
import os 
import numpy as np
import matplotlib.pyplot as plt


output_dir = 'output2'          #設(shè)置輸出文件夾,若不存在則創(chuàng)建
if not os.path.exists(output_dir):
    os.mkdir(output_dir)    

img_file = './../image.png'     #讀取圖片
img = cv2.imread(img_file)

type(img)                       #讀入圖片后得到ndarray 對(duì)象
img.shape                       #ndarray的三個(gè)維度分別是圖片的:高,寬,通道

# pyplot.imgshow 在顯示圖片時(shí)是按照RGB通道順序顯示,cv2則相反
# 需要通過(guò) np.flip(img,axis = 2) 調(diào)整3個(gè)通道的順序(若不調(diào)整圖片顏色失真)
plt.imshow(np.flip(img,axis = 2))
plt.axis('off')
plt.show()                      #圖1

plt.imshow(img)
plt.axis('off')                 #不顯示坐標(biāo)
plt.show()                      #圖2

#輸出并保存圖片
output_image = os.path.join(output_dir,'image.png')
cv2.imwrite(output_image,img)
image.png

4.2 讀取圖片并簡(jiǎn)單處理—圖像特征:顏色直方圖

OpenCV-Python中調(diào)用的直方圖計(jì)算函數(shù)為cv2.calcHist。

"""
hist = cv2.calcHist([image],             # 傳入圖像(列表)
                    [0],                 # 使用的通道(使用通道:可選[0],[1],[2])
                    None,                # 沒(méi)有使用mask(蒙版)
                    [256],               # HistSize
                    [0.0,255.0])         # 直方圖柱的范圍
                                         # return->list
"""

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

def calcAndDrawHist(image, color):  
    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
    histImg = np.zeros([256,256,3], np.uint8)  
    hpt = int(0.9* 256);  
      
    for h in range(256):  
        intensity = int(hist[h]*hpt/maxVal)  
        cv2.line(histImg,(h,256), (h,256-intensity), color)  
    return histImg


if __name__ == '__main__':  
    original_img = cv2.imread("666.png")
    img = cv2.resize(original_img,None,fx=0.6,fy=0.6,interpolation = cv2.INTER_CUBIC)
    b, g, r = cv2.split(img)  
  
    histImgB = calcAndDrawHist(b, [255, 0, 0])  
    histImgG = calcAndDrawHist(g, [0, 255, 0])  
    histImgR = calcAndDrawHist(r, [0, 0, 255])  

    cv2.imshow("histImgB", histImgB)  
    cv2.imshow("histImgG", histImgG)  
    cv2.imshow("histImgR", histImgR)  
    cv2.imshow("Img", img)  
    cv2.waitKey(0)  
    cv2.destroyAllWindows() 

image.png

顏色空間 RGB–HSV–Lab
RGB顏色空間

import cv2
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline 

pic_file = '../data/images/image_crocus_0003.png'

img_bgr = cv2.imread(pic_file, cv2.IMREAD_COLOR) #OpenCV讀取顏色順序:BGR 
img_b = img_bgr[..., 0]
img_g = img_bgr[..., 1]
img_r = img_bgr[..., 2]
fig = plt.gcf()                                  #圖片詳細(xì)信息


fig = plt.gcf()                                  #分通道顯示圖片
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(np.flip(img_bgr, axis=2))             #展平圖像數(shù)組并顯示
plt.axis('off')
plt.title('Image')

plt.subplot(222)
plt.imshow(img_r, cmap='gray')
plt.axis('off')
plt.title('R')

plt.subplot(223)
plt.imshow(img_g, cmap='gray')
plt.axis('off')
plt.title('G')

plt.subplot(224)
plt.imshow(img_b, cmap='gray')
plt.axis('off')
plt.title('B')

plt.show()

image.png

HSV顏色空間

img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
img_h = img_hsv[..., 0]
img_s = img_hsv[..., 1]
img_v = img_hsv[..., 2]

fig = plt.gcf()                      # 分通道顯示圖片
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(img_hsv)
plt.axis('off')
plt.title('HSV')

plt.subplot(222)
plt.imshow(img_h, cmap='gray')
plt.axis('off')
plt.title('H')

plt.subplot(223)
plt.imshow(img_s, cmap='gray')
plt.axis('off')
plt.title('S')

plt.subplot(224)
plt.imshow(img_v, cmap='gray')
plt.axis('off')
plt.title('V')

plt.show()
image.png

Lab*顏色空間

img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)
img_ls = img_lab[..., 0]
img_as = img_lab[..., 1]
img_bs = img_lab[..., 2] 

# 分通道顯示圖片
fig = plt.gcf()
fig.set_size_inches(10, 15)

plt.subplot(221)
plt.imshow(img_lab)
plt.axis('off')
plt.title('L*a*b*')

plt.subplot(222)
plt.imshow(img_ls, cmap='gray')
plt.axis('off')
plt.title('L*')

plt.subplot(223)
plt.imshow(img_as, cmap='gray')
plt.axis('off')
plt.title('a*')

plt.subplot(224)
plt.imshow(img_bs, cmap='gray')
plt.axis('off')
plt.title('b*')

plt.show()  

image.png

灰度圖與其顏色直方圖

img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
fig = plt.gcf()
fig.set_size_inches(5, 7.5)

plt.imshow(img_gray, cmap='gray')
plt.axis('off')
plt.title('Gray')
plt.show()
"""
    cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) → hist
    參數(shù)說(shuō)明
    images:   圖片列表
    channels: 需要計(jì)算直方圖的通道。[0]表示計(jì)算通道0的直方圖,[0,1,2]表示計(jì)算通道0,1,2所表示顏色的直方圖
    mask:     蒙版,只計(jì)算值>0的位置上像素的顏色直方圖,取None表示無(wú)蒙版
    histSize: 每個(gè)維度上直方圖的大小,[8]表示把通道0的顏色取值等分為8份后計(jì)算直方圖
    ranges:   每個(gè)維度的取值范圍,[lower0, upper0, lower1, upper1, ...],lower可以取到,upper無(wú)法取到
    hist:     保存結(jié)果的ndarray對(duì)象
    accumulate: 是否累積,如果設(shè)置了這個(gè)值,hist不會(huì)被清零,直方圖結(jié)果直接累積到hist中
""" 

img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256])

plt.plot(img_gray_hist)
plt.title('Grayscale Histogram')
plt.xlabel('Bins')
plt.ylabel('# of Pixels')
plt.show()
image.png

帶蒙版的顏色直方圖

# 讀取模板
mask_file = '../data/masks/mask_crocus_0003.png'
mask = cv2.imread(mask_file, cv2.IMREAD_UNCHANGED) 
help(cv2.calcHist)
img_gray_hist_with_mask = cv2.calcHist([img_gray], [0], mask, [256], [0, 256])
"""
    圖片按位與
    cv2.bitwise_and(src1, src2[, dst[, mask]]) → dst
    參數(shù)說(shuō)明
        src1: 圖片1
        src2: 圖片2
        dst: 保存結(jié)果的ndarray對(duì)象
        mask: 蒙版 
"""
img_masked = cv2.bitwise_and(img_gray, img_gray, mask=mask)

plt.imshow(img_masked, cmap='gray')
plt.axis('off')
plt.title('Image with mask')
plt.show()

plt.plot(img_gray_hist_with_mask)
plt.title('Grayscale Histogram')
plt.xlabel('Bins')
plt.ylabel('# of Pixels')

plt.show()
image.png

多個(gè)顏色直方圖

# 按R、G、B三個(gè)通道分別計(jì)算顏色直方圖
b_hist = cv2.calcHist([img_bgr], [0], None, [256], [0, 256])
g_hist = cv2.calcHist([img_bgr], [1], None, [256], [0, 256])
r_hist = cv2.calcHist([img_bgr], [2], None, [256], [0, 256])

# 顯示3個(gè)通道的顏色直方圖
plt.plot(b_hist, label='B', color='blue')
plt.plot(g_hist, label='G', color='green')
plt.plot(r_hist, label='R', color='red')
plt.legend(loc='best')
plt.xlim([0, 256])
plt.show()

# 顯示3個(gè)通道的顏色直方圖
plt.plot(b_hist, label='B', color='blue')
plt.plot(g_hist, label='G', color='green')
plt.plot(r_hist, label='R', color='red')
plt.legend(loc='best')
plt.xlim([0, 256])
plt.show()
image.png

按多個(gè)通道計(jì)算顏色直方圖
關(guān)于直方圖均衡詳情 請(qǐng)點(diǎn)擊

# 把一個(gè)像素的多個(gè)通道合在一起看作一個(gè)值
hist = cv2.calcHist([img_bgr], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])

hist.shape
# 含義:B取值在[0, 32), G取值在[0, 32), R取值在[0, 32)的像素個(gè)數(shù)
hist[0, 0, 0]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容