对于256级的8位灰度图,将每一位的灰度拆分出来,生成对应的二值图像,并将不同层次的灰度二值图像组合可以在不损失图像精度的前提下降低图像存储空间。
对应的做法是将不同层次的二值图像分别乘以对应的常数,然后相加即可。
实验证明,将第5,6,7,8层分层二值图像分别乘以对应的对应的常数相加,生成的图像极为接近原图,而且所占用空间变小。
下面我们先分拆灰度原图,将其拆分成8层二值图像。
我们知道,灰度级(0_255)可以用二进制表示,比如灰度值为125的像素,用二进制表示为 0111 1101 ,所以它是在第7位,那么从原灰度图来看,对于第7位,凡是灰度处于[64, 127]的像素点都会在拆分层次的二值图像时,变为1,它的补集[0,63]and[128,255] 都会变为0 ,如此得到第7位的二值图像。
相应的,第1位,二值图像灰度值为1的灰度级区间为[2^0, 2^1) , 即 [0, 2);
第2位,二值图像灰度值为1的灰度级区间为[2^1, 2^2), 即 [2, 4) ;
第3位,二值图像灰度值为1的灰度级区间为[2^2, 2^3), 即 [4, 8) ;
第4位,二值图像灰度值为1的灰度级区间为[2^3, 2^4), 即 [8, 16) ;
第5位,二值图像灰度值为1的灰度级区间为[2^4, 2^5), 即 [16, 32) ;
第6位,二值图像灰度值为1的灰度级区间为[2^5, 2^6), 即 [32, 64) ;
第7位,二值图像灰度值为1的灰度级区间为[2^6, 2^7), 即 [64, 128) ;
第8位,二值图像灰度值为1的灰度级区间为[2^7, 2^8), 即 [128, 256) 。
我们用Python OpenCV 以及Numpy完成上述分拆。
笔者设计了两个函数,分别可以按照输入的数字拆分出相应层次的二值图,也可以将所有的二值层次图全部拆分显示。另外,利用了tqdm模块以可视化运行。
import cv2 as cv
import numpy as np
from tqdm import tqdm
def extract_bit_layer_only_1_layer(input_image, layer_num):
gray=cv.cvtColor(input_image,cv.COLOR_BGR2GRAY)
threshold_limits=[0,2,4,8,16,32,64,128,256]
for row in range(0,gray.shape[0]):
for col in range(0,gray.shape[1]):
gray[row][col]=np.where((gray[row][col]>=threshold_limits[layer_num-1]) and (gray[row][col]<threshold_limits[layer_num]),255,0)
cv.imshow('dst',gray)
def extract_bit_layer_with_8_layers(input_image):
gray=cv.cvtColor(input_image,cv.COLOR_BGR2GRAY)
cv.imshow('gray',gray)
gray1 = np.copy(gray)
gray2 = np.copy(gray)
gray3 = np.copy(gray)
gray4 = np.copy(gray)
gray5 = np.copy(gray)
gray6 = np.copy(gray)
gray7 = np.copy(gray)
gray8 = np.copy(gray)
for row in (range(0,gray.shape[0])):
for col in (range(0,gray.shape[1])):
gray1[row][col]=np.where((gray[row][col]>=0) and (gray[row][col]<2),255,0)
gray2[row][col]=np.where((gray[row][col]>=2) and (gray[row][col]<4),255,0)
gray3[row][col]=np.where((gray[row][col]>=4) and (gray[row][col]<8),255,0)
gray4[row][col]=np.where((gray[row][col]>=8) and (gray[row][col]<16),255,0)
gray5[row][col]=np.where((gray[row][col]>=16) and (gray[row][col]<32),255,0)
gray6[row][col]=np.where((gray[row][col]>=32) and (gray[row][col]<64),255,0)
gray7[row][col]=np.where((gray[row][col]>=64) and (gray[row][col]<128),255,0)
gray8[row][col]=np.where((gray[row][col]>=128) and (gray[row][col]<256),255,0)
cv.imshow('gray1',gray1)
cv.imshow('gray2',gray2)
cv.imshow('gray3',gray3)
cv.imshow('gray4',gray4)
cv.imshow('gray5',gray5)
cv.imshow('gray6',gray6)
cv.imshow('gray7',gray7)
cv.imshow('gray8',gray8)
#gray_rescontruction = np.zeros[]
#print(np.where(gray6[50][50]==255,1,0))
#gray_lists=[gray1,gray2,gray3,gray4,gray5,gray6,gray7,gray8]
#gray_rescontruction = np.copy(gray)
#gray_rescontruction=np.zeros([gray.shape[0], gray.shape[1]], np.uint8)
gray_rescontruction=np.array(gray) * 0
#for i in range(4,8):
#gray_rescontruction += np.array(gray_lists[i]) * (2 ** (i))
for row in range(0,gray.shape[0]):
for col in range(0,gray.shape[1]):
gray_rescontruction[row][col]=(np.where(gray8[row][col]==255,1,0))*128+(np.where(gray7[row][col]==255,1,0))*64+(np.where(gray6[row][col]==255,1,0))*32+(np.where(gray5[row][col]==255,1,0))*16
cv.imshow('gray_rescontruction',gray_rescontruction)
cv.imwrite('E:/Final.jpg',gray_rescontruction)
def rebuild(img_list, build_list):
new_img = np.array(img_list[0]) * 0
for i in build_list:
new_img += np.array(img_list[i]) * (2 ** (i))
return new_img
src= cv.imread('E:\\shanghai.jpg')
extract_bit_layer_with_8_layers(src)
cv.waitKey(0)
以下为程序的运行结果。
保存的最终图片gray_rescontruction 的存储大小为原图像的1/2.