Python隐藏图像数据
小白学视觉 人气:0隐写术是在任何文件中隐藏秘密数据的艺术。
秘密数据可以是任何格式的数据,如文本甚至文件。简而言之,隐写术的主要目的是隐藏任何文件(通常是图像、音频或视频)中的预期信息,而不实际改变文件的外观,即文件外观看起来和以前一样。
在这篇文章中,我们将重点学习基于图像的隐写术,即在图像中隐藏秘密数据。
但在深入研究之前,让我们先看看图像由什么组成:
1.像素是图像的组成部分。
2.每个像素包含三个值:(红色、绿色、蓝色)也称为 RGB 值。
3.每个 RGB 值的范围从 0 到 255。
现在,让我们看看如何将数据编码和解码到我们的图像中。
编码
有很多算法可以用来将数据编码到图像中,实际上我们也可以自己制作一个。在这篇文章中使用的一个很容易理解和实现的算法。
算法如下:
1.对于数据中的每个字符,将其 ASCII 值转换为 8 位二进制 [1]。
2.一次读取三个像素,其总 RGB 值为 3*3=9 个。前八个 RGB 值用于存储一个转换为 8 位二进制的字符。
3.比较相应的RGB值和二进制数据。如果二进制数字为 1,则 RGB 值将转换为奇数,否则为偶数。
4.第 9 个值确定是否应该读取更多像素。如果有更多数据要读取,即编码或解码,则第 9 个像素变为偶数;否则,如果我们想停止进一步读取像素,那就让它变得奇数。
重复这个过程,直到所有数据都被编码到图像中。
例子
假设要隐藏的消息是‘Hii’。
消息是三个字节,因此,对数据进行编码所需的像素为 3 x 3 = 9。考虑一个 4 x 3 的图像,总共有 12 个像素,这足以对给定的数据进行编码。
[(27, 64, 164), (248, 244, 194), (174, 246, 250), (149, 95, 232),
(188, 156, 169), (71, 167, 127), (132, 173, 97), (113, 69, 206),
(255, 29, 213), (53, 153, 220), (246, 225, 229), (142, 82, 175)]
第 1 步
H 的 ASCII 值为 72 ,其二进制等效值为 01001000 。
第 2 步
读取前三个像素。
(27, 64, 164), (248, 244, 194), (174, 246, 250)
第 3 步
现在,将像素值更改为奇数为 1,偶数为 0,就像在二进制等效数据中一样。
例如,第一个二进制数字是0,第一个 RGB 值是 27 ,它需要转换为偶数,这意味着 26 。类似地,64 被转换为 63 因为下一个二进制数字是1 所以 RGB 值应该是奇数。
因此,修改后的像素为:
(26, 63, 164), (248, 243, 194), (174, 246, 250)
第4步
由于我们必须对更多数据进行编码,因此最后一个值应该是偶数。同样,i可以在这个图像中进行编码。
通过执行 +1 或 -1 使像素值成为奇数/偶数时,我们应该注意二进制条件。即像素值应大于或等于 0 且小于或等于 255 。
新图像将如下所示:
[(26, 63, 164), (248, 243, 194), (174, 246, 250), (148, 95, 231),
(188, 155, 168), (70, 167, 126), (132, 173, 97), (112, 69, 206),
(254, 29, 213), (53, 153, 220), (246, 225, 229), (142, 82, 175)]
解码
对于解码,我们将尝试找到如何逆转之前我们用于数据编码的算法。
1.同样,一次读取三个像素。前 8 个 RGB 值为我们提供了有关机密数据的信息,第 9 个值告诉我们是否继续前进。
2.对于前八个值,如果值为奇数,则二进制位为 1 ,否则为 0 。
3.这些位连接成一个字符串,每三个像素,我们得到一个字节的秘密数据,这意味着一个字符。
4.现在,如果第 9 个值是偶数,那么我们继续一次读取三个像素,否则,我们停止。
例如
让我们开始一次读取三个像素。
考虑我们之前编码的图像。
[(26, 63, 164), (248, 243, 194), (174, 246, 250), (148, 95, 231),
(188, 155, 168), (70, 167, 126), (132, 173, 97), (112, 69, 206),
(254, 29, 213), (53, 153, 220), (246, 225, 229), (142, 82, 175)]
第1步
我们首先读取三个像素:
[(26, 63, 164), (248, 243, 194), (174, 246, 250)
第2步
读取第一个值:26,它是偶数,因此二进制位是 0 。类似地,对于 63 ,二进制位是 1 ,对于 164 它是 0 。这个过程一直持续到 8 个 RGB 值。
第 3 步
将所有二进制值连接后,我们最终得到二进制值:01001000。最终的二进制数据对应于十进制值 72,在 ASCII 中,它代表字符 H 。
第 4 步
由于第 9 个值是偶数,我们重复上述步骤。当遇到的第 9 个值是奇数时,我们停止。
结果,我们得到了原始信息,即 Hii 。
上述算法的 Python 程序如下:
# Python program implementing Image Steganography # PIL module is used to extract # pixels of image and modify it from PIL import Image # Convert encoding data into 8-bit binary # form using ASCII value of characters def genData(data): # list of binary codes # of given data newd = [] for i in data: newd.append(format(ord(i), '08b')) return newd # Pixels are modified according to the # 8-bit binary data and finally returned def modPix(pix, data): datalist = genData(data) lendata = len(datalist) imdata = iter(pix) for i in range(lendata): # Extracting 3 pixels at a time pix = [value for value in imdata.__next__()[:3] + imdata.__next__()[:3] + imdata.__next__()[:3]] # Pixel value should be made # odd for 1 and even for 0 for j in range(0, 8): if (datalist[i][j] == '0' and pix[j]% 2 != 0): pix[j] -= 1 elif (datalist[i][j] == '1' and pix[j] % 2 == 0): if(pix[j] != 0): pix[j] -= 1 else: pix[j] += 1 # pix[j] -= 1 # Eighth pixel of every set tells # whether to stop ot read further. # 0 means keep reading; 1 means thec # message is over. if (i == lendata - 1): if (pix[-1] % 2 == 0): if(pix[-1] != 0): pix[-1] -= 1 else: pix[-1] += 1 else: if (pix[-1] % 2 != 0): pix[-1] -= 1 pix = tuple(pix) yield pix[0:3] yield pix[3:6] yield pix[6:9] def encode_enc(newimg, data): w = newimg.size[0] (x, y) = (0, 0) for pixel in modPix(newimg.getdata(), data): # Putting modified pixels in the new image newimg.putpixel((x, y), pixel) if (x == w - 1): x = 0 y += 1 else: x += 1 # Encode data into image def encode(): img = input("Enter image name(with extension) : ") image = Image.open(img, 'r') data = input("Enter data to be encoded : ") if (len(data) == 0): raise ValueError('Data is empty') newimg = image.copy() encode_enc(newimg, data) new_img_name = input("Enter the name of new image(with extension) : ") newimg.save(new_img_name, str(new_img_name.split(".")[1].upper())) # Decode the data in the image def decode(): img = input("Enter image name(with extension) : ") image = Image.open(img, 'r') data = '' imgdata = iter(image.getdata()) while (True): pixels = [value for value in imgdata.__next__()[:3] + imgdata.__next__()[:3] + imgdata.__next__()[:3]] # string of binary data binstr = '' for i in pixels[:8]: if (i % 2 == 0): binstr += '0' else: binstr += '1' data += chr(int(binstr, 2)) if (pixels[-1] % 2 != 0): return data # Main Function def main(): a = int(input(":: Welcome to Steganography ::\n" "1. Encode\n2. Decode\n")) if (a == 1): encode() elif (a == 2): print("Decoded Word : " + decode()) else: raise Exception("Enter correct input") # Driver Code if __name__ == '__main__' : # Calling main function main()
程序中使用的模块是 PIL ,它代表Python 图像库,它使我们能够在 Python 中对图像执行操作。
程序执行
数据编码
数据解码
输入图像
输出图像
局限性
该程序可能无法对 JPEG 图像按预期处理,因为 JPEG 使用有损压缩,这意味着修改像素以压缩图像并降低质量,因此会发生数据丢失。
参考
- https://www.geeksforgeeks.org/program-decimal-binary-conversion/
- https://www.geeksforgeeks.org/working-images-python/
- https://dev.to/erikwhiting88/let-s-hide-a-secret-message-in-an-image-with-python-and-opencv-1jf5
- A code along with the dependencies can be found here: https://github.com/goelashwin36/image-steganography
加载全部内容