[OpenCV筆記] 1.影像處理之位元運算 & ROI加密實作
1.影像加法運算
有 2 種方法,分別為 "+" 或使用函式 cv2.add(a, b),效果說明如下:
使用 "+",若a+b > 255,則會取mod。
使用函式 cv2.add(a, b)若a+b的值大於255,計算結果則為255。
執行程式後的效果如下:
<source:greatway9999>由於使用 "+"是取mod運算,當a+b > 255,取mod後會比原來的值還小,讓原本應該更亮的像素點變得更暗。
而使用函式 cv2.add(a, b),當a+b > 255時,輸出為255,因此像素相加後,增加像素值,讓原本的圖像更亮。
1.1 程式碼
import numpy as np
import cv2
a = cv2.imread('Lenna.jpg')
cv2.imshow('original',a)
b = a
result1 = a + b
result2 = cv2.add(a, b)
cv2.imshow('a+b',result1)
cv2.imshow('cv2.add(a, b)',result2)
cv2.waitKey()
cv2.destroyAllWindows()
2.影像加權和
計算2張影像像素和,依照需求,給予不同的權重。兩張影像的大小必須相等。函示如下:
cv2.addWeighted(src1, src1之權重, src2, src2之權重, 亮度調節量)
3.逐位元邏輯運算
3.1.逐位元AND運算
And運算的特色如下:
任何數值與 0 運算,會得到 0。
任何數值與 255 運算,會得到數值本身。
使用逐位元AND運算產生的效果為保留設定區域內的圖,相當於原圖與遮罩進行And之位元運算後,得到就是遮罩大小的原圖。如下圖所示:
<source:greatway9999>其程式如下 :
import numpy as np
import cv2
a = cv2.imread('Lenna.jpg')
b = np.zeros(a.shape, dtype=np.uint8)
b[50:150, 50:150] = 255
b[50:160, 50:60] = 255
c = cv2.bitwise_and(a,b)
print('a.shpae=', a.shape)
print('b.shape=', b.shape)
cv2.imshow('original',a)
cv2.imshow('mask',b)
cv2.imshow('result',c)
cv2.waitKey()
cv2.destroyAllWindows()
3.2.逐位元OR運算
使用逐位元OR運算產生的效果和AND運算相反,為保留設定區域外的圖,相當於原圖與遮罩進行OR之位元運算後,去除遮罩大小的原圖。如下圖所示:
<source:greatway9999>其程式如下 :
import numpy as np
import cv2
a = cv2.imread('Lenna.jpg')
b = np.zeros(a.shape, dtype=np.uint8)
b[50:150, 50:150] = 255
b[50:160, 50:60] = 255
c = cv2.bitwise_or(a,b)
print('a.shpae=', a.shape)
print('b.shape=', b.shape)
cv2.imshow('original',a)
cv2.imshow('mask',b)
cv2.imshow('result',c)
cv2.waitKey()
cv2.destroyAllWindows()
3.3.逐位元NOT運算
使用逐位元NOT運算,即將原本影像的0轉換成1,1轉換成0,所得效果如下圖:
<source:greatway9999>其程式如下 :
import numpy as np
import cv2
a = cv2.imread('Lenna.jpg')
c = cv2.bitwise_not(a)
print('a.shpae=', a.shape)
cv2.imshow('original',a)
cv2.imshow('result',c)
cv2.waitKey()
cv2.destroyAllWindows()
3.4.逐位元XOR運算
使用逐位元XOR運算產生的效果,即使用一個遮罩與原圖進行XOR運算,最後在遮罩範圍內得到一個與原圖位元相反的圖像,而遮罩外的圖片仍和原圖一樣,如下圖所示。
<source:greatway9999>其程式如下 :
import numpy as np
import cv2
a = cv2.imread('Lenna.jpg')
b = np.zeros(a.shape, dtype=np.uint8)
b[50:150, 50:150] = 255
b[50:160, 50:60] = 255
c = cv2.bitwise_xor(a, b)
print('a.shpae=', a.shape)
print('b.shape=', b.shape)
cv2.imshow('original',a)
cv2.imshow('mask',b)
cv2.imshow('result',c)
cv2.waitKey()
cv2.destroyAllWindows()
3.5.位元平面分解
越高位元,對影像像素值影響越大,如第7個位元平面所示,與原圖最接近。
<source:greatway9999>其程式如下 :
#位元平面分解
import numpy as np
import cv2
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('Lenna', img)
# Step1.獲取影像資訊
r, c = img.shape #顯示影像列寬*行高
# Step2.建立分析矩陣
x = np.zeros((r, c, 8), dtype=np.uint8) #建立一個位元分析矩陣,大小為 r*c*8。8表示分析灰階影像的第8個位元平面。
for i in range(8): #設定用於分析各個位元平面的分析矩陣之值
x[:,:,i] = 2 ** i
print(x)
#Step3. 分析位元平面
bitplane = np.zeros((r, c, 8), dtype=np.uint8)
for i in range(8): #進行各位元平面分析
bitplane[:,:,i] = cv2.bitwise_and(img, x[:,:,i])
mask = bitplane[:,:,i]>0 #將位元平面中大於0的值設為True,小於0的值設為False
# Step4.設定值處理
bitplane[mask] = 255 #讓二值化影像可以清楚黑白顯示
cv2.imshow(str(i), bitplane[:,:,i]) #顯示各位元影像
cv2.waitKey()
cv2.destroyAllWindows()
3.6.影像加密與解密
影像加解密可透過逐位元的互斥 (XOR) 運算實現。
bitwise_xor(原圖, 金鑰) = 加密影像
bitwise_xor(加密影像, 金鑰) = 解密影像
其程式如下 :
#影像加密與解密
import numpy as np
import cv2
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('Lenna', img)
r, c = img.shape #顯示影像列寬*行高
key = np.random.randint(0, 256, size=(r, c), dtype = np.uint8)
encryption = cv2.bitwise_xor(img, key)
decryption = cv2.bitwise_xor(encryption, key)
cv2.imshow('key', key)
cv2.imshow('encryption', encryption)
cv2.imshow('decryption', decryption)
cv2.waitKey()
cv2.destroyAllWindows()
3.7. 綜合演練-針對指定區域(眼睛)加密
ROI為有興趣的區域,本練習為運用上述技巧,針對ROI進行加密。假設要針對圖片人物的右眼加密,效果如下圖:
<source:greatway9999>實作順序說明如下:
Step1. 讀圖
Step2. 建立與原圖大小相同的遮罩和ROI區域
Step3. 建立與原圖大小相同的金鑰
Step4. 用金鑰對原圖加密並取得加密的ROI區域
Step5. 取得ROI外區域的內容並與Step4 結果相加即可滿足題意所要求之結果
其程式如下 :
#針對ROI區域加密
import numpy as np
import cv2
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE) #以灰階的方式顯示圖片
r, c = img.shape #顯示影像列寬*行高
#建立遮罩
mask = np.zeros(img.shape, dtype=np.uint8) #建立一個和原圖大小相同的遮罩
mask[150:180, 150:180] = 1 #在遮罩範圍中,設定ROI為1,其餘區域為0
#建立加密與解密用之金鑰
key = np.random.randint(0, 256, size=(r, c), dtype = np.uint8) #建立一個和原圖大小相同的金鑰,每個像素值介於0~256
#各種情況的加密
encrypt_img = cv2.bitwise_xor(img, key) #對原始影像加密
encrypt_ROI = cv2.bitwise_and(encrypt_img, mask*255) #取加密後的ROI
bg = cv2.bitwise_or(img, mask*255) #取mask外的背景。任何數值與255運算會得到數值本身,因此透過此設定保留我們要的區域。
#bg = cv2.bitwise_and(img, (1-mask)*255) #另一種取背景的方法
encrypt_ROI_img = encrypt_ROI + bg #將加密的區域與背景相加
print('img.shpae=', img.shape) #顯示原圖列寬和行高
print('mask.shape=', mask.shape) #顯示遮罩列寬和行高
cv2.imshow('original',img) #顯示原圖
cv2.imshow('mask',mask) #顯示遮罩
cv2.imshow('encrypt_img', encrypt_img) #顯示加密後的原圖
cv2.imshow('encrypt_ROI', encrypt_ROI) #顯示加密後的原圖ROI
cv2.imshow('bg', bg) #顯示ROI外的圖
cv2.imshow('encrypt_ROI_img', encrypt_ROI_img) #顯示整張圖片與加密的ROI區域
cv2.waitKey()
cv2.destroyAllWindows()
<source:greatway9999>
本文之Github Code:
#影像位元運算
---
0 留言