1. 程式人生 > 其它 >opencv入門系列教學(五)影象的基本操作(畫素值、屬性、ROI和邊框)

opencv入門系列教學(五)影象的基本操作(畫素值、屬性、ROI和邊框)

0.序言

每個影象是由一個個點組成的,而這些點可以表示為畫素值的形式。

這篇部落格裡我們將學會:

  • 訪問畫素值並修改它們 。
  • 訪問影象屬性 。
  • 設定感興趣區域(ROI) 。
  • 分割和合並影象。

對於影象的基本操作我們需要對numpy知識的瞭解,不需要很多,只知道基本用法即可。這裡暫不贅述,讀者可查閱其餘資料進行學習。

1.訪問和修改畫素值

讓我們先載入彩色影象:

import numpy as np
import cv2 as cv

img = cv.imread('cat.jpg')

我們可以通過行和列座標來訪問畫素值。對於 BGR 影象,它返回一個由藍色、綠色和紅色值組成的陣列。而如果是灰度影象的話,它只返回相應的灰度。我們也可以用相同的方式來對畫素值進行修改。

# 通過行和列座標來訪問畫素值
>>> px = img[100,100]
>>> print( px )
[157 166 200]

# 修改畫素值
>>> img[100,100] = [255,255,255]
>>> print( img[100,100] )
[255 255 255]

Numpy是用於快速陣列計算的優化庫。因此,簡單地訪問每個畫素值並對其進行修改將非常慢,因此不建議使用。對於單個畫素訪問,Numpy陣列方法array.item()和array.itemset())被認為更好,但是它們始終返回標量。如果要訪問所有B,G,R值,則需要分別呼叫所有的array.item()。

比如我們可以用下面的方法來進行畫素的訪問和編輯:

# 訪問 RED 值
>>> img.item(10,10,2)
59

# 修改 RED 值
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100

2.訪問影象屬性

影象屬性包括行數,列數,通道數,影象資料型別,畫素數等等。
影象的形狀可通過 img.shape 訪問。它返回行,列和通道數的元組(如果影象是彩色的)

注意:如果影象是灰度的,則返回的元組僅包含行數和列數,因此這是檢查載入的影象是灰度還是彩色的好方法。

>>> print
( img.shape ) (342, 548, 3)

畫素總數可通過訪問 img.size :

>>> print( img.size )
562248

影象資料型別通過 img.dtype 獲得:

>>> print( img.dtype )
uint8

注意:img.dtype在除錯時非常重要,因為OpenCV-Python程式碼中的大量錯誤是由無效的資料型別引起的。

3.影象感興趣區域ROI

有時候,我們不得不處理一些特定區域的影象。比如對於影象中的眼睛檢測,首先對整個影象進行人臉檢測。在獲取人臉影象時,我們只選擇人臉區域,搜尋其中的眼睛,而不是搜尋整個影象。它提高了準確性和效能。

這裡我們直接使用numpy的切片即可,比如:

>>> ROI = img[280:340, 330:390]

不規則形狀的ROI區域的設定,我們將在以後的文章裡再詳細闡述。

4.拆分和合並影象通道

有時我們需要分別處理影象的B,G,R通道。在這種情況下,我們需要將BGR影象拆分為單個通道。我們可以這樣做:

>>> b,g,r = cv.split(img) >>> img = cv.merge((b,g,r))

但是cv.split() 是一項耗時的操作(就時間而言)。因此,僅在必要時才這樣做。我們一般採用Numpy索引的方法。比如我們要將所有的紅色畫素都設定為0:

>>> img [:, :, 2] = 0

5.為影象設定邊框

如果我們要在影象周圍建立邊框(如相框),那可以使用 cv.copyMakeBorder() 。它在以後對影象進行高階處理的時候,比如卷積運算,零填充等方面將有更多應用。此函式採用以下引數:

  • src - 輸入影象
  • top,bottom,left,right 邊界寬度(以相應方向上的畫素數為單位)
  • borderType - 定義要新增哪種邊框的標誌。它可以是以下型別:
  • cv.BORDER_CONSTANT - 新增恆定的彩色邊框。該值應作為下一個引數給出。
  • cv.BORDER_REFLECT - 邊框將是邊框元素的映象,如下所示: fedcba | abcdefgh hgfedcb
  • **cv.BORDER_REFLECT_101**或 **cv.BORDER_DEFAULT**與上述相同,但略有變化,例如: gfedcb | abcdefgh | gfedcba
  • **cv.BORDER_REPLICATE**最後一個元素被複制,像這樣: aaaaaa | abcdefgh | hhhhhhh
  • **cv.BORDER_WRAP**看起來像這樣: cdefgh | abcdefgh | abcdefg
  • value -邊框的顏色,如果邊框型別為**cv.BORDER_CONSTANT**

下面我們來看一下各個邊框型別在圖片顯示上的結果。注意因為影象是基於matplotlib一起顯示的。所以紅色和藍色通道將會互換。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
BLUE = [255,0,0]
img1 = cv.imread('opencv-logo.png')
replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP)
constant= cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()

結果如下: