Opencv-Python 學習之旅 - 2

Core Operations

Posted by Bobson Lin on Wednesday, December 12, 2018

影像基本運算


import cv2

img = cv2.imread('data/messi5.jpg')
px = img[100, 100]
print(px, px.shape, px.size, px.dtype, type(px))

# accessing only blue pixel
blue = img[100, 100, 0]
print(blue, type(blue))

img[100, 100] = [255, 255, 255]
img[100, 101] = [255, 255, 255]
print(img[100, 100])

# accessing RED value
print(img.item(10, 10, 2))

# modifying RED value
img.itemset((10, 10, 2), 100)
print(img.item(10, 10, 2))

print(img.shape, img.size, img.dtype, type(img))

ball = img[280:340, 330:390]
img[273:333, 100:160] = ball

b, g, r = cv2.split(img)
img_m = cv2.merge((b, g, r))
img[:, :, 2] = 0
print(id(img), id(img_m))

[157 166 200] | (3,) 3 uint8
157 | () 1 uint8
[255 255 255]
59
100
(342, 548, 3) 562248 uint8
140225644633904 140225188020512

  • cv2.imread 讀取進影像的數據矩陣,利用 Numpy 套件的資料結構儲存,而每格的型態為numpy.uint8 (0~255)。
  • 基本上讀取進來彩色影像是三維矩陣(numpy.ndarray)。
  • 影像的矩陣;img[列, 行, (顏色資訊)],若是預設的 flag 應為 BGR,也就是彩色影像;彩色影像的顏色資訊有3個[藍 綠 紅]數值,而灰階影像只會有1個數值。
  • 對於矩陣的操作可以使用 Operations on Arrays 裡的函數,或直接操作 Numpy Array
  • 相關 API 文檔 Operations on ArraysNumpy Indexing

影像算術運算


import cv2

ml_img = cv2.imread('data/ml.png')
logo_img = cv2.imread('data/opencv-logo.png')
logo_imgROI = logo_img[179:559, 146:454]
print(ml_img.shape, logo_img.shape, logo_imgROI.shape)

# dst = cv2.addWeighted(ml_img, 0.7, logo_img, 0.3, 0)
dst = cv2.addWeighted(ml_img, 0.7, logo_imgROI, 0.3, 0)

cv2.imshow('dst', dst)
cv2.imshow('ml', ml_img)
cv2.imshow('logo', logo_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

注意:
Opencv 的相加函數 和 Numpy Array 的相加 的結果會不一樣。
舉例來說:
>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print(cv2.add(x,y)) # 250+10 = 260 => 255
>>> print(x+y) # 250+10 = 260 % 256 = 4

  • 影像相加時須用 cv2.addcv2.addWeighted 函數。
  • 另外相加的影像大小不一樣時需要先定義 感興趣區域(ROI),否則會出現 error: (-209:Sizes of input arguments do not match) 的錯誤訊息。
  • 合成結果: addWeighted_dst
import cv2

# Load two images
img1 = cv2.imread('data/messi5.jpg')
img2 = cv2.imread('data/opencv-logo-white.png')

# I want to put logo on top-left corner, So I create a ROI
rows, cols, channels = img2.shape
print(img1.shape, img2.shape)
roi = img1[0:rows, 0:cols]

# Now create a mask of logo and create its inverse mask also
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)

# Now black-out the area of logo in ROI
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)

# Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2, img2, mask=mask)

# Put logo in ROI and modify the main image
dst = cv2.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst

cv2.imshow('res', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 另外也可以用邏輯運算去作合成,如 cv2.bitwise_andcv2.bitwise_not
  • cv2.threshold 可以設置的門檻來過濾或處理圖片,後面章節會在提。
  • 合成結果: bitwise_dst

效能測量與優化技術


由於這需要與實作上後更容易了解這塊,之後再更新。
參考

你也可以瞧瞧…

參考

系列文