04 OpenCV位平面分解

简介: 位平面分解的核心思想是将图像的每一个像素分解为多个二进制位,分别存储在不同的位平面上。例如,如果一个图像是8位深度的,则可以分解为8个位平面,每个位平面上存储一个二进制位。

1 基本概念


位平面分解的核心思想是将图像的每一个像素分解为多个二进制位,分别存储在不同的位平面上。例如,如果一个图像是8位深度的,则可以分解为8个位平面,每个位平面上存储一个二进制位。


位平面分解在图像压缩中有着重要的应用,因为它可以有效减少图像的存储大小。例如,如果一个图像的最高位平面(即最高二进制位)存储的是图像的主要信息,那么将其单独存储可以大大减小图像的大小。


此外,位平面分解技术的应用非常广泛,除了压缩技术以外,在数字水印、和特征提取等方面都有重要的应用。通过对每个位平面进行单独处理,可以更加精细地处理图像信息,提高图像处理的效率和精度。


1.1 位平面分解流程:

读入灰度图像并将其转换为二进制形式,即将每个像素点的灰度值表示成8位二进制数。

对于每个像素点的二进制数,将它们按位拆分为8个二进制数,每个数表示一个位平面。

对于每个位平面,将其转换为0或255的二值图像。具体方法是将每个像素点的该位的二进制数值提取出来,然后将该值赋为0或255。这样就可以得到8个二值图像,每个图像表示了原图像中某一位上的信息。

保存每个位平面的二值图像,以便后续使用。

1.2 位平面分解算法原理

假设原图像为 I ( x , y ) I(x,y)I(x,y),灰度级为 g ( x , y ) g(x,y)g(x,y),每个像素点的灰度值可以表示成一个8位的二进制数,即 image.png

,其中 b 7 b_7b 7 到 b 0 b_0b0  分别表示第7位到第0位的二进制值,取值为0或1。


对于第 i ii 个位平面,可以通过如下公式将其转换为0或255的二值图像



image.png

这里 b i b_ib i  表示 g ( x , y ) g(x,y)g(x,y) 的第 i ii 位二进制值。


因此,可以将原图像 I ( x , y ) I(x,y)I(x,y) 的每个像素点的二进制值拆分成8个位平面,得到8个二值图像 P 0 ( x , y ) , P 1 ( x , y ) , ⋯   , P 7 ( x , y ) P_0(x,y), P_1(x,y), \cdots, P_7(x,y)P

0 (x,y),P 1 (x,y),⋯,P 7 (x,y),它们表示了原图像中的信息在每个二进制位上的分布情况。


举个例子,当我们的原始数据像素数据为:


24d94c24ec785b9224fb59f05415187b.png




则首先将其格式转为二进制:




1dfbd6e7ce5f3142a760f1411dd862de.png


之后将二进制的各位分别取出,就形成了分解后的位平面:



dcd999d0bf786500c293161f7f4e3ce7.png



2 位平面分解的Python实现


使用OpenCV的imread函数读入一幅灰度图像,灰度值范围为0~255,并用imshow函数显示原图像。

import cv2  
import numpy as np  
# 读入灰度图像并显示  
lena = cv2.imread("lenacolor.png", 0)  
cv2.imshow("lena", lena)


获取图像的尺寸,即行数和列数。

# 获取图像的尺寸  
r, c = lena.shape
1


构造表示二进制位的图像,即构造8个大小与原图像大小相同的图像,每个图像上的像素值表示二进制数值的某一位。即

( 1 , 2 , 4 , . . . , 128 )

如换算成二进制则为

( 00000001 , 00000010 , 00000100 , . . . , 10000000 )

# 构造表示二进制位的图像  
x = np.zeros((r, c, 8), dtype=np.uint8)  
for i in range(8):  
    x[:, :, i] = 2 ** i  
print(x)




e6d89971e7564ce0511c2356a37fdbbd.png


其中x=np.zeros((r, c,8), dtype=np.uint8)语句设置一个用于提取各个位平面的提取矩阵。该矩阵是“r×c×8”大小的,其中r是行高,c是列宽,8表示共有8个通道。矩阵x的8个通道分别用来提取灰度图像的8个位平面。例如,x[:, :,0]用来提取灰度图像的第0个位平面。


构造表示每个位平面的图像,即将原图像的每个像素的二进制数值按位拆分,并将对应位平面上的像素值赋为该二进制位的数值,其余像素值为0。并执行二进制维度上的AND关系。使用OpenCV的位运算 AND 可以直接执行上述操作。与运算的讲解点此查看

# 构造表示每个位平面的图像,并显示  
r = np.zeros((r, c, 8), dtype=np.uint8)  
for i in range(8):  
    # 使用位运算 AND 获取当前位平面的二值图像  
    r[:, :, i] = cv2.bitwise_and(lena, x[:, :, i])


将当前位平面的非零像素值赋为255,将该位平面的二值图像转换为0/255的形式。这是因为位平面分解后的图像应为二值图像,而Python在展示是默认为8位像素。因此我们要将二值的0或1转化为8位的0或255。

for i in range(8):  
    # 使用位运算 AND 获取当前位平面的二值图像  
    r[:, :, i] = cv2.bitwise_and(lena, x[:, :, i])  
    print(r)  
    # 将非零像素值赋为255,将当前位平面的二值图像转换为0/255的形式  
    mask = r[:, :, i] > 0  
    r[mask] = 255


最后,使用imshow函数显示当前位平面的二值图像。完整的函数如下:

import cv2  
import numpy as np  
# 读入灰度图像并显示  
lena = cv2.imread("lenacolor.png", 0)  
#cv2.imshow("lena", lena)  
# 获取图像的尺寸  
r, c = lena.shape  
# 构造表示二进制位的图像  
x = np.zeros((r, c, 8), dtype=np.uint8)  
for i in range(8):  
    x[:, :, i] = 2 ** i  
print(x)  
# 构造表示每个位平面的图像,并显示  
r = np.zeros((r, c, 8), dtype=np.uint8)  
for i in range(8):  
    # 使用位运算 AND 获取当前位平面的二值图像  
    r[:, :, i] = cv2.bitwise_and(lena, x[:, :, i])  
    print(r)  
    # 将非零像素值赋为255,将当前位平面的二值图像转换为0/255的形式  
    mask = r[:, :, i] > 0  
    r[mask] = 255  
    # 显示当前位平面的二值图像  
    cv2.imshow(str(i), r[:, :, i])  
# 等待用户按下任意键,然后关闭所有窗口  
cv2.waitKey()  
cv2.destroyAllWindows()


最终,图象被分解成了8张二值图像。并且位数越高的二值图像,越能体现出原始图像的特征。

e89b5a69424d297b390008995a9168b8.png




相关文章
|
2月前
|
计算机视觉 Python
OpenCV 4基础篇| OpenCV图像的拆分和合并
OpenCV 4基础篇| OpenCV图像的拆分和合并
|
5月前
|
编解码 算法 计算机视觉
OpenCV(十七):拉普拉斯图像金字塔
OpenCV(十七):拉普拉斯图像金字塔
63 0
|
7月前
|
计算机视觉
openCV的卷积操作
openCV的卷积操作
37 0
|
计算机视觉 索引
三天学会opencv(二)——矩阵的掩膜操作
三天学会opencv(二)——矩阵的掩膜操作
三天学会opencv(二)——矩阵的掩膜操作
|
存储 API 计算机视觉
OpenCV 矩阵的掩膜操作
OpenCV 矩阵的掩膜操作
118 0
OpenCV 矩阵的掩膜操作
|
计算机视觉 C语言 Linux
|
Web App开发 计算机视觉
opencv2.4中SVD分解的几种调用方法
原帖地址: http://blog.sina.com.cn/s/blog_6109b5d00101ag7a.html       在摄影测量和计算机视觉中,考虑最优解问题时,经常要用到SVD分解。
1782 0
|
算法 计算机视觉
OpenCV学习(20) grabcut分割算法
在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好。算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts 比如下面的一副图,我们只要选定一个四边形框,把框中的图像作为grabcut的一个输入参数,表示该框中的像素可能属于前景,但框外的部分一定属于背景。
1522 0