案例參考自《OpenCV輕松入門:面向Python》
【例3.1】分別使用加號運算符和函數cv2.add()計算兩幅灰度圖像的像素值之和,觀察處理結果
使用+號相加的結果 \(value=(a+b)\%{255}\)
使用cv庫相加的結果
\( value= \begin{cases} a+b,a+b\leq255\\ 255,a+b>255\ \end{cases} \)
加權和計算方式為
\( value=saturate(v1 *\alpha+v2 *\beta+\gamma) \)
v1和v2代表兩個像素點的值,\(\alpha\) , \(\beta\)是權重系數, \(\gamma\)是偏置項
import cv2 as cv
import matplotlib.pyplot as plt
lenna = cv.imread('../img/lenna512.bmp', cv.IMREAD_GRAYSCALE)
boat = cv.imread('../img/boat.bmp', cv.IMREAD_GRAYSCALE)
copy = lenna.copy()
add = lenna+copy
cv_add = cv.add(lenna, copy)
cv_weight_add = cv.addWeighted(lenna, 0.7, boat, 0.3, 0)
plt.subplot(2,2,1),plt.title('lenna'),plt.axis('off'),plt.imshow(lenna, cmap='gray')
plt.subplot(2,2,2),plt.title('add'),plt.axis('off'),plt.imshow(add, cmap='gray')
plt.subplot(2,2,3),plt.title('cv_add'),plt.axis('off'),plt.imshow(cv_add, cmap='gray'),
plt.subplot(2,2,4),plt.title('cv_weight_add_boat_lenna'),plt.axis('off'),plt.imshow(cv_weight_add, cmap='gray'),
plt.show()
【例3.2】構造一個掩模圖像,使用按位與運算保留圖像中被掩模指定的部分。使用掩模和不使用掩模
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
lenna = cv.imread('../img/lenna_color.png', cv.IMREAD_COLOR)
lenna = lenna[:, :, [2, 1, 0]]
and_img = np.zeros(lenna.shape, dtype=np.uint8)
and_img[100:400, 200:400] = 255
and_img[100:500, 100:200] = 255
mask = np.zeros((lenna.shape[0], lenna.shape[1]), dtype=np.uint8)
mask[100:400, 200:400] = 255
mask[100:500, 100:200] = 255
no_mask_bitwise_and = cv.bitwise_and(lenna, and_img)
mask_bitwise_and = cv.bitwise_and(lenna, lenna, mask=mask)
plt.figure(figsize=(9, 6))
plt.subplot(2,3,1),plt.title('lenna'),plt.axis('off'),plt.imshow(lenna)
plt.subplot(2,3,2),plt.title('mask(1 channels)'),plt.axis('off'),plt.imshow(mask, cmap='gray')
plt.subplot(2,3,3),plt.title('and_img(3 channels)'),plt.axis('off'),plt.imshow(and_img)
plt.subplot(2,3,4),plt.title('no_mask_bitwise_and'),plt.axis('off'),plt.imshow(no_mask_bitwise_and)
plt.subplot(2,3,5),plt.title('mask_bitwise_and'),plt.axis('off'),plt.imshow(mask_bitwise_and)
plt.show()
【例3.3】位平面分解,將一副圖像位平面分解並顯示。
8位灰度圖中,每個像素的值可以如下按位分解
\( value= a_7* {2^7}+ a_6*2^6+ a_5 *2^5+ a_4 *2^4+ a_3 *2^3+ a_2 *2^2+ a_1 *2^1+ a_0 *2^0 \)
\(a_7\)權重最大,對圖像影響最大; \(a_0\)權重最小,對圖像影響最小。
按每位分解可以得到位圖(位平面),\(a_7\)是最高有效位平面(第7位平面),\(a_0\)是最低有效位平面(第0位平面)
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 輸入圖片的路徑,獲得圖片的8個位圖
def get_bitmaps(image):
bit_extraction = []
bit_images = []
for i in range(8):
bit_extraction.append(np.ones(image.shape, dtype=np.uint8)*pow(2, i))
for i in range(8):
bit_images.append(cv.bitwise_and(image, bit_extraction[i]))
return bit_images
lenna = cv.imread('../img/lenna_color.png', cv.IMREAD_COLOR)
lenna = lenna[:, :, [2, 1, 0]]
gray_lenna = cv.cvtColor(lenna, cv.COLOR_BGR2GRAY)
gray_bit_images = get_bitmaps(gray_lenna)
color_bit_images = get_bitmaps(lenna)
plt.figure(figsize=(12,12))
plt.suptitle('gray image bitmap', fontsize=16)
plt.subplot(3,3,1),plt.axis('off'),plt.title('lenna'),plt.imshow(gray_lenna, cmap='gray')
for i in range(8):
plt.subplot(3,3,i+2),plt.axis('off'),plt.title('bit_img_'+str(i)),plt.imshow(gray_bit_images[i], cmap='gray')
plt.show()
plt.figure(figsize=(12,12))
plt.suptitle('color image bitmap', fontsize=16)
plt.subplot(3,3,1),plt.axis('off'),plt.title('lenna'),plt.imshow(lenna)
for i in range(8):
plt.subplot(3,3,i+2),plt.axis('off'),plt.title('bit_img_'+str(i)),plt.imshow(color_bit_images[i])
plt.show()
可以看到分解的位平面圖中
灰度圖中第3~7位平面像素值依次增大,顯示的效果越好,低位平面圖接近黑白色。
彩色圖中第4~7位平面像素值依次增大,顯示的效果越好,低位平面圖接近黑色。
【例3.4】位平面分解,將一副圖像位平面分解並顯示。
低位圖對原圖像的影響十分的小,用低位圖的最后一位來保存另一張圖片的信息,這樣就可以在一張圖片里存儲另一張圖片的信息(數字水印)
下面是處理過程,輸出的是圖片,人眼直觀上看不出圖片之間的差別,但其實圖5(從左到右從上到下)是包含了兩張圖片的信息。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
#讀入圖片
lenna = cv.imread('../img/lenna512.bmp', cv.IMREAD_GRAYSCALE)
watermark = cv.imread('../img/watermark.bmp', cv.IMREAD_GRAYSCALE)
#構建提取矩陣
extraction = np.ones(lenna.shape, dtype=np.uint8)*254
#去掉圖像的最低位
lenna_lowest_bit_discarded = cv.bitwise_and(lenna, extraction)
#水印圖片二值化處理
watermark_binary = watermark.copy()
watermark_binary[watermark_binary[:,:]>0] = 1
#嵌入水印圖片
lenna_watermark = cv.bitwise_or(lenna_lowest_bit_discarded, watermark_binary)
#提取水印
extraction_watermark = cv.bitwise_and(lenna_watermark, np.ones(lenna_watermark.shape, dtype=np.uint8))
img_list = [lenna, watermark,lenna_lowest_bit_discarded,watermark_binary,lenna_watermark,extraction_watermark]
img_name_list = ['lenna', 'watermark','lenna_lowest_bit_discarded','watermark_binary','lenna_watermark','extraction_watermark']
plt.figure(figsize=(9, 6))
for i in range(len(img_list)):
plt.subplot(2, 3, i+1)
plt.axis('off')
plt.title(img_name_list[i])
plt.imshow(img_list[i], cmap='gray')
plt.show()