OpenCV 中文官方文檔:http://woshicver.com/
圖像基本操作:
- 通路像素值并修改它們
- 通路圖像屬性
- 設定感興趣區域(ROI)
- 分割和合并圖像
圖像運算主要有:圖像加法和圖像融合
實作效果:塗紅一塊區域;複制一塊區域;僅顯示藍色通道;将紅色通道置0
import numpy as np
import cv2 as cv
# 通路和修改像素值
image = cv.imread("keyboard.webp")
# 通過行和列坐标來通路像素值。對于 BGR 圖像,它傳回一個由藍色、綠色和紅色值組成的數組。對于灰階圖像,隻傳回相應的灰階
px = image[10, 10]
print(px) # [45 36 29]
# 通路藍色像素
print(image[10, 10, 0]) # 45
# 修改像素值
# note: Numpy是用于快速數組計算的優化庫。是以,簡單地通路每個像素值并對其進行修改将非常緩慢
# 這種方法通常用于選擇數組的區域,例如前5行和後3列
image[10:80, 10:80] = [0, 0, 255]
print(image[10, 10]) # [ 0 0 255]
cv.imshow("image", image)
cv.waitKey(0)
cv.destroyAllWindows()
# 對于單個像素通路,Numpy數
# 組方法array.item()和array.itemset())被認為更好,但是它們始終傳回标量
# .item() 隻能通路單通道
print(image.item(10, 10, 2)) # 255
image.itemset((10, 10, 2), 100)
print(image.item(10, 10, 2)) # 100
####################################################################
# 通路圖像屬性:行數,列數和通道數,圖像資料類型,像素數
# .shape 傳回行、列和通道數 (行和列下标都是從0開始);如果圖像是灰階的,則傳回的元組僅包含行數和列數
print(image.shape) # (340, 510, 3)
# 像素總數
print(image.size) # 520200 = 340*510*3
# 圖像資料類型
print(image.dtype) # uint8
####################################################################
# 圖像感興趣區域ROI: 比如找人眼,可以先确定人臉區域,然後在這個區域搜尋眼睛,而不用搜尋整張圖像
# 可以使用numpy索引
region = image[100:200, 100:200]
image[200:300, 200:300] = region
cv.imshow("image", image)
cv.waitKey(0)
cv.destroyAllWindows()
####################################################################
# 拆分、合并圖像通道
# cv.split() 是一項耗時的操作(就時間而言)。是以,僅在必要時才這樣做。否則請進行Numpy索引
b, g, r = cv.split(image)
print(b.shape) # (340, 510)
cv.imshow("image", b)
cv.waitKey(0)
cv.destroyAllWindows()
# 下面更快
# b = image[:, :, 0]
# 将紅色通道設為紅色
image[:, :, 2] = 0
cv.imshow("image", image)
cv.waitKey(0)
cv.destroyAllWindows()
# 合并通道
img = cv.merge((b, g, r))
圖像運算
圖像加法:
- 兩個圖像應具有相同的深度和類型
- OpenCV函數cv.add():飽和運算 250+10 = 260 => 255 (推薦)
- Numpy操作:模運算 250+10 = 260 % 256 = 4
圖像融合:
- 也是圖像加法,但是對圖像賦予不同的權重,以使其具有融合或透明的感覺
實際效果:分别是飽和運算、模運算和按權重融合
import numpy as np
import cv2 as cv
image1 = cv.imread("keyboard.webp")
image2 = cv.imread("background.jpg")
print(image1.shape) # (340, 510, 3)
print(image2.shape) # (175, 146, 3)
image3 = image1[:175, :146]
des1 = cv.add(image2, image3)
des2 = image2 + image3
des3 = cv.addWeighted(image2, 0.3, image3, 0.7, 0)
# show
cv.imshow("image", image2)
cv.waitKey(0)
cv.imshow("image", image3)
cv.waitKey(0)
cv.imshow("image", des1)
cv.waitKey(0)
cv.imshow("image", des2)
cv.waitKey(0)
cv.imshow("image", des3)
cv.waitKey(0)
cv.destroyAllWindows()
按位運算:
import numpy as np
import cv2 as cv
image1 = cv.imread("keyboard.webp")
image2 = cv.imread("background.jpg")
print(image1.shape) # (340, 510, 3)
print(image2.shape) # (175, 146, 3)
image1Copy = image1.copy()
rows, cols, channels = image2.shape
# 處理的區域
roi = image1[:rows, :cols]
# 現在建立logo的掩碼,并同時建立其相反掩碼
image2gray = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(image2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
# 現在将ROI中logo的區域塗黑
image1_bg = cv.bitwise_and(roi, roi, mask=mask_inv)
# 僅從logo圖像中提取logo區域
image2_fg = cv.bitwise_and(image2, image2, mask=mask)
# 将logo放入ROI并修改主圖像
dst = cv.add(image1_bg, image2_fg)
image1[:rows, :cols] = dst
# show
cv.imshow("image", image1Copy)
cv.waitKey(0)
cv.imshow("image", image2)
cv.waitKey(0)
cv.imshow("image", image1)
cv.waitKey(0)
cv.destroyAllWindows()