21. 影像的疊加
兩張影像直接進行加法運算后影像的顏色會改變,通過加權加法實作影像混合后影像的透明度會改變,都不能實作影像的疊加,
實作影像的疊加,需要綜合運用影像閾值處理、影像掩模、位操作和影像加法的操作,
我們以 Lena 影像疊加 CVlogo 為例,討論影像疊加的思路和步驟:
- 確定影像疊加位置,將 Lena 影像中的疊加位置裁剪出來,使疊加影像的尺寸相同;
- 對前景影像進行二值化處理,生成黑白掩模影像 mask(LOGO區域黑色遮蓋)及其反轉掩模影像 maskInv (LOGO區域白色開窗);
- 以黑白掩模 mask(LOGO區域黑色遮蓋)作為掩模,對背景影像(Lena裁剪圖)進行位操作,LOGO區域遮蓋為黑色,其它區域保持不變,得到疊加背景影像 img1BG;
- 以反轉掩模 maskInv(LOGO區域白色開窗)作為掩模,對前景影像(CVlogo)進行位操作,LOGO區域保持不變,其它區域遮蓋為黑色,得到疊加前景影像 img2FG;
- 背景影像 img1BG 和 前景影像 img2FG 通過 cv2.add 加法運算,得到裁剪部分的疊加影像;
- 用疊加影像替換Lena 影像中的疊加位置,得到Lena 疊加 CVlogo 的影像,

基本例程:1.30 影像的疊加
# 1.30 影像的疊加
img1 = cv2.imread("../images/imgLena.tif") # 讀取彩色影像(BGR)
img2 = cv2.imread("../images/logoCV.png") # 讀取 CV Logo
x, y = (0, 10) # 影像疊加位置
W1, H1 = img1.shape[1::-1]
W2, H2 = img2.shape[1::-1]
if (x + W2) > W1: x = W1 - W2
if (y + H2) > H1: y = H1 - H2
print(W1,H1,W2,H2,x,y)
imgROI = img1[y:y+W2, x:x+H2] # 從背景影像裁剪出疊加區域影像
img2Gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # img2: 轉換為灰度影像
ret, mask = cv2.threshold(img2Gray, 175, 255, cv2.THRESH_BINARY) # 轉換為二值影像,生成遮罩,LOGO 區域黑色遮蓋
maskInv = cv2.bitwise_not(mask) # 按位非(黑白轉置),生成逆遮罩,LOGO 區域白色開窗,LOGO 以外區域黑色
# mask 黑色遮蓋區域輸出為黑色,mask 白色開窗區域與運算(原影像素不變)
img1Bg = cv2.bitwise_and(imgROI, imgROI, mask=mask) # 生成背景,imgROI 的遮罩區域輸出黑色
img2Fg = cv2.bitwise_and(img2, img2, mask=maskInv) # 生成前景,LOGO 的逆遮罩區域輸出黑色
# img1Bg = cv2.bitwise_or(imgROI, imgROI, mask=mask) # 生成背景,與 cv2.bitwise_and 效果相同
# img2Fg = cv2.bitwise_or(img2, img2, mask=maskInv) # 生成前景,與 cv2.bitwise_and 效果相同
# img1Bg = cv2.add(imgROI, np.zeros(np.shape(img2), dtype=np.uint8), mask=mask) # 生成背景,與 cv2.bitwise 效果相同
# img2Fg = cv2.add(img2, np.zeros(np.shape(img2), dtype=np.uint8), mask=maskInv) # 生成背景,與 cv2.bitwise 效果相同
imgROIAdd = cv2.add(img1Bg, img2Fg) # 前景與背景合成,得到裁剪部分的疊加影像
imgAdd = img1.copy()
imgAdd[y:y+W2, x:x+H2] = imgROIAdd # 用疊加影像替換背景影像中的疊加位置,得到疊加 Logo 合成影像
plt.figure(figsize=(9,6))
titleList = ["1. imgGray", "2. imgMask", "3. MaskInv", "4. img2FG", "5. img1BG", "6. imgROIAdd"]
imageList = [img2Gray, mask, maskInv, img2Fg, img1Bg, imgROIAdd]
for i in range(6):
plt.subplot(2,3,i+1), plt.title(titleList[i]), plt.axis('off')
if (imageList[i].ndim==3): # 彩色影像 ndim=3
plt.imshow(cv2.cvtColor(imageList[i], cv2.COLOR_BGR2RGB)) # 彩色影像需要轉換為 RGB 格式
else: # 灰度影像 ndim=2
plt.imshow(imageList[i], 'gray')
plt.show()
cv2.imshow("imgAdd", imgAdd) # 顯示疊加影像 imgAdd
key = cv2.waitKey(0) # 等待按鍵命令
例程說明 1.30:
- 本例程實作影像的疊加,中間程序影像如上圖所示,最終的疊加影像如下圖所示,
- 影像疊加所涉及的操作步驟較多,建議將上文的步驟說明與程式、中間程序影像相互對照進行閱讀,
- 使用位操作生成前景 img1Bg 時,使用掩模影像 mask 對 imgROI 與 imgROI 進行 “與操作”,而不是直接對 mask 與 imgROI 進行操作,是因為 mask 為灰度影像而 imgROI 為彩色影像,不能直接進行加法或位操作,
- 使用位操作生成前景、背景影像時,遮罩區域以外 imgROI 與 imgROI 進行 “自與操作”,如果用 “自或操作” (參見程式注釋陳述句)的效果也是相同的,此處甚至也可以用加法操作 cv2.add 實作(參見程式注釋陳述句),但位操作的運算速度更快,
- 函式 threshold() 將灰度影像轉換為二值影像(Binarization),只有黑白兩色,該方法通過固定閾值 thresh 處理影像,將像素點的灰度值設為 0 或 255,

歡迎關注『Python 小白從零開始 OpenCV 學習課 @ youcans』 系列,持續更新中
Python 大白從零開始 OpenCV 學習課-1.安裝與環境配置
Python 大白從零開始 OpenCV 學習課-2.影像讀取與顯示
Python 大白從零開始 OpenCV 學習課-3.影像的創建與修改
Python 大白從零開始 OpenCV 學習課-4.影像的疊加與混合
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/356205.html
標籤:其他
