我想提取图像RGB值的最低有效位,并将这些位转换为等效的ascii。问题是我在python中循环使用numpy矩阵的方法非常慢。使用Java时采用相同的策略大约快100倍。图像尺寸不超过1024 * 1024,因此生成的矩阵最大尺寸为1024 * 1024 * 3.
根据python文档的append函数是O(1)时间复杂度,我的循环是O(n ^ 2),其中n <= 1024.我理解python使用解释器而Java使用JIT编译器进行编译因此要快得多。但是,这里的时差太大了。
这项操作能否以更有效的方式完成?
def extract_info_from_lsb(self, path):
lsb_message_result = []
matrix = self.image_to_matrix(path)
for row in matrix:
lsb_message_list = []
for pixel in row:
for color in pixel:
lsb = color & 1
lsb_message_list.append(lsb)
lsb_message_result.append(lsb_message_list)
for i, lsb_message in enumerate(lsb_message_result):
lsb_message_result[i] = self.text_from_bits(lsb_message)
return lsb_message_result
我采用的将二进制值转换为ascii的函数如下:
def text_from_bits(self, bits):
chars = []
for b in range(len(bits) / 8):
byte = bits[b * 8:(b + 1) * 8]
chars.append(chr(int(''.join([str(bit) for bit in byte]), 2)))
return ''.join(chars)
将图像转换为矩阵的功能是:
def image_to_matrix(self, path):
image = Image.open(path)
matrix = np.array(image)
return matrix
答案 0 :(得分:2)
从ndarray获取LSB的一种快速方法是对模运算进行向量化(即将其应用于整个数组)让numpy进行循环(参见注释):
def extract_info_from_lsb(self, path):
lsb_message_result = []
matrix = self.image_to_matrix(path)
matrix = matrix.astype(int) # make sure the data type is integer (redundant)
lsb_matrix = matrix % 2 # modulo two to get the LSB of each element
lsb_message_result = lsb_matrix.ravel() # flatten to a 1D array
lsb_message_result = lsb_message_result.tolist() # optional: convert to list
矢量化转换为ASCII(假设图像中的像素数是8的精确倍数):
def text_from_bits(self, bits):
bits = np.reshape(bits, (-1, 8)) # matrix with 8 elements per row (1 byte)
bitvalues = [128, 64, 32, 16, 8, 4, 2, 1]
bytes = np.sum(bits * bitvalues, axis=1) # rows to bytes
chars = [chr(b) for b it bytes] # convert each byte to a character and put into a list
return ''.join(chars)
请注意,您将获得0到255范围内的ASCII值。这不是严格的ASCII,传统上只在0 - 127范围内。
相关的绩效相关概念: