Python位图切割
Henry_zs 人气:01. 介绍
图像的像素值是由比特组成的。例如一副256级灰度图像中,图像是由8 bit组成。
与之前对比度拉伸的区别是,之前我们主要强调在某一范围的灰度值作为我们能感兴趣的目标将其变亮或者变暗。而位图切割主要强调每个bit对图像的贡献,通过方法将不同位的灰度值值取出来还原成图像。
如图所示,一副8 bit图像,我们可以将图像分割成8个,将每个图像对应的比特位取出构建成一副新的图像
2. 实现方法
例如图像某一点的像素值为100,对应的二进制为0110 0100
我们的目标很简单,就是将第1位的0取出来(这里不要把100看成一个数,将他想象成一幅图像的所有点,我们要把图像像素对应二进制的第一位全部取出,组成一副新的图像)以此类推...
最后为了防止取出的灰度值过暗,我们将他映射到最大值255
这里提供两种方法实现:
- 将图像的二进制和对应的 8bit 相与(0000 0000),例如取第0个比特平面的话图像就和(0000 0001)与。所以结果只能是0000 000X (X取决于图像的最低位),如果X = 1的话,我们认为这个点的像素在 0bit平面有值,将它映射为255;否则为0
- 图像像素除以 2^n (n代表第n个比特平面,n从0开始,为了满足编程下标从0开始计数),如果商的整数部分为1的话,说明这个点在n比特平面有值,映射为255;否则为0
注:
- 这里映射为255为了突出对应比特平面的亮度,否则就算再最高的比特平面,最大值也只有128灰度值(因为最高的是第7为,2^7 = 128)
- 如果利用第一种与的方法,但是最后不要拉伸成255,只是把与的结果作为新的图像输出。那么只需要将8副图像全部加起来就可以还原图像
3. code
这里用第二种÷的方法实现
如果用第一种与的方法的话,只需要将中间的代码段替换成后面的就行,结果是一样的
import cv2 import numpy as np gray = cv2.imread('./img.jpg',0) img = cv2.resize(gray,None,fx = 0.5,fy = 0.5,interpolation=cv2.INTER_AREA) #缩小图像 group = [] # 存放每一层的图像 for n in range(8): dst = np.zeros_like(img) for i in range(img.shape[0]): for j in range(img.shape[1]): ret = img[i][j] // pow(2,n) #ret = img[i][j] & pow(2,n) if (ret % 2) ==1: # if (ret ==pow(2,n)): dst[i][j] = 255 else: dst[i][j] = 0 group.append(dst) cv2.imshow('0-3',np.hstack((i for i in group[:4]))) cv2.imshow('4-7',np.hstack((i for i in group[4:]))) cv2.waitKey() cv2.destroyAllWindows()
输入图像:
输出结果:
4. 比特平面重建图像
如果还原图像的话,我们再输出图像的时候,就不要映射到255,之间将图像与比特平面相与的结果输出即可
import cv2 import numpy as np gray = cv2.imread('./img.jpg',0) img = cv2.resize(gray,None,fx = 0.5,fy = 0.5,interpolation=cv2.INTER_AREA) #缩小图像 group = [] # 存放每一层的图像 for n in range(8): dst = np.zeros_like(img) for i in range(img.shape[0]): for j in range(img.shape[1]): ret = img[i][j] & pow(2,n) dst[i][j] = ret # 将与的结果作为图像 group.append(dst) cv2.imshow('0-3',np.hstack((i for i in group[:4]))) cv2.imshow('4-7',np.hstack((i for i in group[4:]))) a = np.zeros_like(img) # 还原 for i in group: a += i cv2.imshow('img',a) cv2.waitKey() cv2.destroyAllWindows()
输出比特平面:
所以图像相加为:
加载全部内容