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()

結果如下:

 

 

 

 

 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM