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(加密影像, 金鑰) = 解密影像


<source:greatway9999>

其程式如下 :

#影像加密與解密

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:

https://github.com/greatway9999/OpenCV_Basic/blob/main/computer_vision_basic_and_bitwise_practice.ipynb


#影像位元運算 

---

0 留言