什么是位平面分解
将灰度图像中处于统一比特位上的二进制像素值进行组合,得到一副二进制图像,该图像被称为灰度图像的一个位平面,这个过程被称为位平面分解。例如,将一副灰度图像内所有像素点上处于二进制位内的最低位上的值进行组合,可以构成“最低有效位”位平面。
在8位灰度图像中,每一个像素使用8位二进制来表示,其值的范围在[0,255]之间,从低到高的分别位:
00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000
取这些值之后,我们通过按位与运算,就可以得到所有位平面分解图。至于有什么用呢?聪明的小伙伴肯定知道。比如,我们需要给一个图像添加水印,是在高位平面添加好,还是最低有效位平面添加好呢?
当然是低位平面,因为它的信息最少,添加水印后,去除水印也比较容易。
灰度图位平面分解
既然,我们了解了灰度位平面分解以及它的所有知识。下面,我们就来获取一张绘图图像,提取它的所有位平面图。
具体代码如下所示:
import cv2 import numpy as np a = cv2.imread("4.jpg", 0) r, c = a.shape b = np.zeros((r, c, 8), dtype=np.uint8) for i in range(8): b[:, :, i] = 2 ** i for i in range(8): temp = cv2.bitwise_and(a, b[:, :, i]) cv2.imshow(str(i),temp) cv2.waitKey() cv2.destroyAllWindows()
运行之后,我们得到灰度图像的8个位平面图:
而原图是这样的:
彩色图位平面分解
既然灰度图像有其位平面,那么彩色图像同样也可以提取出来。但是因为彩色图像的矩阵为3维矩阵,所以我们需要给RGB的每个颜色值进行按位与运算。
具体代码如下所示:
import cv2 import numpy as np a = cv2.imread("4.jpg", -1) x, y, z = a.shape b = np.zeros((x, y, 8), dtype=np.uint8) for i in range(8): b[:, :, i] = 2 ** i temp = np.zeros((x, y, 3), dtype=np.uint8) for i in range(8): temp[:, :, 0] = cv2.bitwise_and(a[:, :, 0], b[:, :, i]) temp[:, :, 1] = cv2.bitwise_and(a[:, :, 1], b[:, :, i]) temp[:, :, 2] = cv2.bitwise_and(a[:, :, 2], b[:, :, i]) cv2.imshow(str(i), temp) cv2.waitKey() cv2.destroyAllWindows()
运行之后,我们会得到下面8张位平面图:
阈值
不知道,读者注意到了没有,不管是灰度图像还是彩色图像,其0-4位图的细节几乎看不到,都是黑色的。这个时候如何让其细节更加凸显呢?
答案是改变其阈值,它们数值肯定非常小,我们直接把其更改为255,除0之外都可以凸显其细节出来。现在我们把彩色位图提取的代码更改一下,代码如下:
import cv2 import numpy as np a = cv2.imread("4.jpg", -1) x, y, z = a.shape b = np.zeros((x, y, 8), dtype=np.uint8) for i in range(8): b[:, :, i] = 2 ** i temp = np.zeros((x, y, 3), dtype=np.uint8) for i in range(8): temp[:, :, 0] = cv2.bitwise_and(a[:, :, 0], b[:, :, i]) temp[:, :, 1] = cv2.bitwise_and(a[:, :, 1], b[:, :, i]) temp[:, :, 2] = cv2.bitwise_and(a[:, :, 2], b[:, :, i]) m = temp[:, :] > 0 temp[m] = 255 cv2.imshow(str(i), temp) cv2.waitKey() cv2.destroyAllWindows()
运行之后,效果如下所示:
彩色位平面图合成
既然有分解,那么肯定有合成。所以我们也需要掌握如何将所有位平面合成为一张图。代码如下:
import cv2 import numpy as np a = cv2.imread("4.jpg", -1) x, y, z = a.shape b = np.zeros((x, y, 8), dtype=np.uint8) for i in range(8): b[:, :, i] = 2 ** i bit_img = np.zeros((x, y, 3), dtype=np.uint8) temp = np.zeros((x, y, 3), 'uint8') for i in range(8): bit_img[:, :, 0] = cv2.bitwise_and(a[:, :, 0], b[:, :, i]) bit_img[:, :, 1] = cv2.bitwise_and(a[:, :, 1], b[:, :, i]) bit_img[:, :, 2] = cv2.bitwise_and(a[:, :, 2], b[:, :, i]) temp[:, :, 0] = cv2.bitwise_or(temp[:, :, 0], bit_img[:, :, 0]) temp[:, :, 1] = cv2.bitwise_or(temp[:, :, 1], bit_img[:, :, 1]) temp[:, :, 2] = cv2.bitwise_or(temp[:, :, 2], bit_img[:, :, 2]) m = bit_img[:, :] > 0 bit_img[m] = 255 #cv2.imshow(str(i)+".bmp",bit_img) cv2.imshow('00000000', temp) cv2.waitKey() cv2.destroyAllWindows()
这里,我们通过按位或bitwise_or函数合并为位平面图。运行之后,temp就是原图,而bit_img就是位平面图。这样我们在实际处理的时候,能在中间对位平面图bit_img进行操作后,在合并为一张图。
灰度位平面图合成
彩色比灰度要复杂的多,灰度位平面图合并就相对较为简单。话不多说,我们直接上代码:
import cv2 import numpy as np a = cv2.imread("4.jpg", 0) r, c = a.shape b = np.zeros((r, c, 8), dtype=np.uint8) for i in range(8): b[:, :, i] = 2 ** i c=np.zeros((r,c),dtype=np.uint8) for i in range(8): temp = cv2.bitwise_and(a, b[:, :, i]) c=cv2.bitwise_or(c,temp) cv2.imshow("111",c) cv2.waitKey() cv2.destroyAllWindows()