1. 程式人生 > >2 用python進行OpenCV實戰之影象基本知識

2 用python進行OpenCV實戰之影象基本知識

前言

在這一節,我們將學習影象的基本構成單元——畫素,我們將詳細的探討什麼是畫素?畫素是如何使用來構成影象的?然後學習如何通過OpenCV來獲取和操縱畫素。

1 什麼是畫素

所有的影象都包含一組畫素,畫素是影象的原始構建塊。 沒有比畫素更細的單位了。
通常,我們將畫素認為是在我們的影象給定位置出現的光的顏色或者強度,如果我們將影象考慮成一個網格,在網格中的每個方塊都包含一個單一的畫素。例如,我們假設有一個解析度是500*300的影象,這就意味著我們的影象被分成一個關於畫素的網格,這個網格有500個行,300個列,綜上可知,總共有500*300=150000個畫素在這張圖片中。
畫素主要有兩種表達形式:灰度模式和彩色模式。在一張灰度圖片中,每個畫素有一個從0至255{[0,255]}的值,其中0表示“純黑色”,255表示“純白色”,在0和255之間的值變現成不同深淺的灰色,當值靠近0時,影象更暗,當值靠近255時,影象更亮。
彩色模式的圖片通常用RGB顏色空間來表示(R for red, G for green, B for blue),還有一些其他的模式比如CMY,但是在這裡我們先不討論。
我們以(red, green, blue)的形式來表示RGB元組,這個元組就表示了我們的顏色,其中這三種顏色的值用在[0,255]之間的整數值表示,所以我們通常用unsigned int型別來表示每個顏色的強度。
為了構成白色,我們需要用(255, 255, 255)來表示,為了得到黑色,我們需要用(0, 0, 0)來表示,紅(255, 0, 0),綠(0, 255, 0),藍(0, 0, 255).

RGB配色表
色光三原色

2 影象座標系概述

正如我們之前所提到的,我們將一張圖片以畫素網格的形式表示,我們想象一下假設我們的圖片為一張圖表紙,影象的左上角為原點。
影象座標系

3 獲取和操縱畫素

上一節中,我們從磁碟中讀取了圖片,然後將它轉換了格式再儲存到了磁碟中,在這一節我們將對如何獲取和操縱影象的畫素進行實戰,建立

getting_and_setting.py

3.1 程式碼

from __future__ import print_function #1
import argparse #2
import cv2 #3

ap = argparse.ArgumentParser
() #4 ap.add_argument("-i", "--image", required=True, help="Path to the image") #5 args = vars(ap.parse_args()) #6 image = cv2.imread(args["image"]) #7 cv2.imshow("Original", image) #8 (b, g, r) = image[0, 0] #9 print("Pixel at (0, 0) - Red: {}, Green: {}, Blue: {}".format(r, g, b)) #10
image[0, 0] = (0, 0, 255) #11 (b, g, r) = image[0, 0] #12 print("Pixel at (0, 0) - Red: {}, Green: {}, Blue: {}".format(r, g, b)) #13 corner = image[0:200, 0:100] #14 cv2.imshow("corner1", corner) #15 image[0:200, 0:100] = (0, 255, 0) #16 cv2.imshow("update", image) #17 cv2.waitKey(0) #18

3.2 程式碼詳細解釋

#1-6:
關於這段程式碼在第一節中已經進行過詳細解釋了,主要是為了導包,命令列引數的處理

#7-8:
展示原始圖片

#9:
在第一節中,就曾經提到過OpenCV是用NumPy陣列來表示影象的,我們也可以將這種表示看成是一種矩陣表示,為了獲取畫素,我們需要應用我們所感興趣的x,y座標,從中我們可以得到一個表示(r,g,b)的元組,然而,我們需要注意的是:在OpenCV中是以逆序儲存RGB通道到的,即我們通常以red,green,blue的順序來記憶,但是OpenCV則是以blue,green,red的順序來儲存的.

(b, g, r) = image[0, 0]

通過獲得影象(0,0)處的畫素,並將它賦值給一個三元組,我們可以再次看出OpenCV以逆序存取RGB畫素,所以當我們在元組中得到每個元素時候,我們需要以BGR的順序來獲取

#10:
輸出RGB每個通道的值到終端。可以看出我們獲取畫素值的方法非常簡單,而這一切都要歸功於NumPy,它替我們做了一系列的複雜工作。

#11:
我們操縱在左上角的畫素,即在(0,0)處的畫素,我們給他賦值(0,0,255),如果我們將它以RGB的格式來讀的話,我們認為:red值是0,green值是0,blue值是255,所以我們將得到純藍色。然而,正如我們之前所提到的OpenCV是以BGR的格式儲存畫素的而不是RGB格式,所以我們實際上得到的是:red值是255,green值是0,blue值是0,因此我們得到的是一個純紅色而不是純藍色。

#12,13:
通過得到在(0,0)畫素點的BGR顏色值,然後將它們以RGB的形式輸出

#14
獲取以及操縱單一的畫素點是相當簡單的,那如果使用NumPy的陣列分割能力得到影象的一塊長方形區域呢?

corner = image[0:200, 0:100] #14

在第一節我們介紹過image的數組裡的第一個引數是高即y,第二個引數是寬即x,所以corner將得到一個100*200大小的長方形區域,而這個區域即為影象的左上角區域。

#15:
將corner以“Corner”的名稱顯示出來

#16:
將左上角的區域用(0,255,0)即綠色來表示,實現了改變一整塊區域的畫素值的目的。

#17:
以“Updated”的名稱顯示影象

#18:
cv2.waitKey()表示暫停指令碼的執行直到在鍵盤輸入一個按鍵,用“0”作為引數表示可以使用任何按鍵作為繼續指令碼執行的按鈕。

效果展示

顯示效果