OpenCV_Python官方文件7+——按位運算之給影象加logo
阿新 • • 發佈:2018-12-16
OpenCV-Python Tutorials
按位運算
包括按位與(AND)、按位或(OR)、按位非(NOT)、按位異或(XOR)等運算。
按位運算的用途:比如要得到一個加logo的影象。如果將兩幅圖片直接相加會改變圖片的顏色,如果用影象混合,則會改變圖片的透明度,這時候就需要用按位操作,既不改變影象顏色,又不改變影象透明度,類似PS。
這裡需要了解一個術語——掩膜(mask)是用一副二值化圖片對另外一幅圖片進行區域性的遮擋。
主要函式
cv2.bitwise_and()
:位與運算,有0則為0, 全為1則為1cv2.bitwise_not()
:或運算,有1則為1, 全為0則為0cv2.bitwise_or()
cv2.bitwise_xor()
:異或運算,不同為1, 相同為0
按位運算的圖片效果展示請點選這裡
ret, dst = cv2.threshold(src, thresh, maxval,type)
:閾值(二值化操作),閾值又叫臨界值,是指一個效應能夠產生的的最低值或最高。
dst
: 輸出影象src
: 輸入影象,只能輸入單通道影象,一般為灰度圖thresh
: 閾值maxval
: 當畫素值大於閾值(或者小於閾值,根據type來決定),所賦予的值type
:閾值操作的型別----每種型別圖片效果展示點選這裡- cv2.THRESH_BINARY #二元閾值
- cv2.THRESH_BINARY_INV #逆二元閾值,
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2.THRESH_TOZERO_INV
例項:將OpenCV的logo加到圖片為沙漠的左上角,要求有顏色的區域為不透明的。
思路就是把原圖中要放logo的區域摳出來,再把logo填到空出來的區域上。
1. 讀取圖片
關於讀取圖片路徑問題請點選此處檢視
import cv2 import numpy as np import matplotlib.pyplot as plt import os os.chdir('C:/Users/lenovo/Pictures/') img1 = cv2.imread('desert.jpg') #沙漠圖片 img2 = cv2.imread('opencv_logo.jpg') #logo圖片 #img2 = cv2.imread('opencv_logo.jpg',0) #也可以讀取logo的時候直接灰度化
2. 根據logo大小提取感興趣區域roi
# 把logo放在左上角,提取原圖中要放置logo的區域roi
rows, cols = img2.shape[:2]
roi = img1[:rows, :cols]
3. 建立掩膜mask
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) #將圖片灰度化,如果在讀取logo時直接灰度化,該步驟可省略
#如果一個畫素值低於200,則畫素值轉換為255(白色色素值),否則轉換成0(黑色色素值)
#即有內容的地方為黑色0,無內容的地方為白色255.
#白色的地方還是白色,除了白色的地方全變成黑色
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)#闕值操作
mask_inv = cv2.bitwise_not(mask) #與mask顏色相反,白色變成黑色,黑變白
4. logo與感興趣區域roi融合
關於cv2.add(img1,img2)
函式點選此處檢視
# 保留除logo外的背景
img1_bg = cv2.bitwise_and(roi, roi, mask=mask)
img2_fg = cv2.bitwise_and(img2,img2,mask=mask_inv)
dst = cv2.add(img1_bg, img2_fg) # logo與感興趣區域roi進行融合
img1[:rows, :cols] = dst # 將融合後的區域放進原圖
img_new_add = img1.copy() #對處理後的影象進行拷貝
5. 顯示每步處理後的圖片
可以用cv2.show()
來顯示圖片,也可以用matplotlib中的函式來顯示。注意:在matplotlib中圖片的顏色模式為RGB,而OpenCV中為BGR模式,所以顯示圖片前要先調整顏色通道順序。用到cv2.split()
和cv2.merge()
函式,這兩個函式前面有寫到,點選檢視。
'''
# 顯示圖片,呼叫opencv展示
cv2.imshow('logo',img2)
cv2.imshow('logo_gray',img2gray)
cv2.imshow('logo_mask',mask)
cv2.imshow('logo_mask_inv',mask_inv)
cv2.imshow('roi',roi)
cv2.imshow('img1_bg',img1_bg)
cv2.imshow('img2_fg',img2_fg)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
'''
# cv2與matplotlib的影象顏色模式轉換,cv2是BGR格式,matplotlib是RGB格式
def img_convert(cv2_img):
# 灰度圖片直接返回
if len(cv2_img.shape) == 2:
return cv2_img
# 3通道的BGR圖片
elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 3:
b, g, r = cv2.split(cv2_img) #分離原影象通道
return cv2.merge((r, g, b)) #合併新的影象通道
# 4通道的BGR圖片
elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 4:
b, g, r, a = cv2.split(cv2_img)
return cv2.merge((r, g, b, a))
# 未知圖片格式
else:
return cv2_img
# 顯示圖片,呼叫matplotlib展示
titles = ['logo','logo_gray','logo_mask','logo_mask_inv','roi','img1_bg','img2_fg','dst']
imgs = [img2,img2gray,mask,mask_inv,roi,img1_bg,img2_fg,dst]
for i in range(len(imgs)):
plt.subplot(2,4,i+1),plt.imshow(img_convert(imgs[i]),'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
# 顯示加logo的圖片
cv2.imshow('img_new_add',img_new_add)
cv2.waitKey(0)
cv2.destroyAllWindows()
原始碼
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
os.chdir('C:/Users/lenovo/Pictures/')
# 1. 讀取圖片
img1 = cv2.imread('desert.jpg') #讀取沙漠圖片
img2 = cv2.imread('opencv_logo.jpg') #讀取logo圖片
#img2 = cv2.imread('opencv_logo.jpg',0) #也可以讀取logo的時候直接灰度化
# 2. 根據logo大小提取感興趣區域roi
# 把logo放在左上角,提取原圖中要放置logo的區域roi
rows, cols = img2.shape[:2]
roi = img1[:rows, :cols]
# 3. 建立掩膜mask
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) #將圖片灰度化,如果在讀取logo時直接灰度化,該步驟可省略
#cv2.THRESH_BINARY:如果一個畫素值低於200,則畫素值轉換為255(白色色素值),否則轉換成0(黑色色素值)
#即有內容的地方為黑色0,無內容的地方為白色255.
#白色的地方還是白色,除了白色的地方全變成黑色
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)#闕值操作
mask_inv = cv2.bitwise_not(mask) #與mask顏色相反,白色變成黑色,黑變白
# 4. logo與感興趣區域roi融合
# 保留除logo外的背景
img1_bg = cv2.bitwise_and(roi, roi, mask=mask)
img2_fg = cv2.bitwise_and(img2,img2,mask=mask_inv)
dst = cv2.add(img1_bg, img2_fg) # logo與感興趣區域roi進行融合
img1[:rows, :cols] = dst # 將融合後的區域放進原圖
img_new_add = img1.copy() #對處理後的影象進行拷貝
# 5. 顯示每步處理後的圖片
'''
# 顯示圖片,呼叫opencv展示
cv2.imshow('logo',img2)
cv2.imshow('logo_gray',img2gray)
cv2.imshow('logo_mask',mask)
cv2.imshow('logo_mask_inv',mask_inv)
cv2.imshow('roi',roi)
cv2.imshow('img1_bg',img1_bg)
cv2.imshow('img2_fg',img2_fg)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
'''
# cv2與matplotlib的影象顏色模式轉換,cv2是BGR格式,matplotlib是RGB格式
def img_convert(cv2_img):
# 灰度圖片直接返回
if len(cv2_img.shape) == 2:
return cv2_img
# 3通道的BGR圖片
elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 3:
b, g, r = cv2.split(cv2_img) #分離原影象通道
return cv2.merge((r, g, b)) #合併新的影象通道
# 4通道的BGR圖片
elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 4:
b, g, r, a = cv2.split(cv2_img)
return cv2.merge((r, g, b, a))
# 未知圖片格式
else:
return cv2_img
# 顯示圖片,呼叫matplotlib展示
titles = ['logo','logo_gray','logo_mask','logo_mask_inv','roi','img1_bg','img2_fg','dst']
imgs = [img2,img2gray,mask,mask_inv,roi,img1_bg,img2_fg,dst]
for i in range(len(imgs)):
plt.subplot(2,4,i+1),plt.imshow(img_convert(imgs[i]),'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
# 顯示並儲存加logo的圖片
cv2.imshow('img_new_add',img_new_add)
cv2.imwrite('img_new_add.jpg',img_new_add)
cv2.waitKey(0)
cv2.destroyAllWindows()
執行結果:
每步處理後的圖片
最終加logo的圖片展示: