opencv基础-位平面分解和图像运算

案例参考自《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()

posted @ 2020-12-15 22:36  赝·goodfellow  阅读(1280)  评论(0编辑  收藏  举报