詳解如何使用Python隱藏圖像中的數(shù)據(jù)

隱寫術(shù)是在任何文件中隱藏秘密數(shù)據(jù)的藝術(shù)。
秘密數(shù)據(jù)可以是任何格式的數(shù)據(jù),如文本甚至文件。簡(jiǎn)而言之,隱寫術(shù)的主要目的是隱藏任何文件(通常是圖像、音頻或視頻)中的預(yù)期信息,而不實(shí)際改變文件的外觀,即文件外觀看起來(lái)和以前一樣。
在這篇文章中,我們將重點(diǎn)學(xué)習(xí)基于圖像的隱寫術(shù),即在圖像中隱藏秘密數(shù)據(jù)。
但在深入研究之前,讓我們先看看圖像由什么組成:
1.像素是圖像的組成部分。
2.每個(gè)像素包含三個(gè)值:(紅色、綠色、藍(lán)色)也稱為 RGB 值。
3.每個(gè) RGB 值的范圍從 0 到 255。
現(xiàn)在,讓我們看看如何將數(shù)據(jù)編碼和解碼到我們的圖像中。
編碼
有很多算法可以用來(lái)將數(shù)據(jù)編碼到圖像中,實(shí)際上我們也可以自己制作一個(gè)。在這篇文章中使用的一個(gè)很容易理解和實(shí)現(xiàn)的算法。
算法如下:
1.對(duì)于數(shù)據(jù)中的每個(gè)字符,將其 ASCII 值轉(zhuǎn)換為 8 位二進(jìn)制 [1]。
2.一次讀取三個(gè)像素,其總 RGB 值為 3*3=9 個(gè)。前八個(gè) RGB 值用于存儲(chǔ)一個(gè)轉(zhuǎn)換為 8 位二進(jìn)制的字符。
3.比較相應(yīng)的RGB值和二進(jìn)制數(shù)據(jù)。如果二進(jìn)制數(shù)字為 1,則 RGB 值將轉(zhuǎn)換為奇數(shù),否則為偶數(shù)。
4.第 9 個(gè)值確定是否應(yīng)該讀取更多像素。如果有更多數(shù)據(jù)要讀取,即編碼或解碼,則第 9 個(gè)像素變?yōu)榕紨?shù);否則,如果我們想停止進(jìn)一步讀取像素,那就讓它變得奇數(shù)。
重復(fù)這個(gè)過(guò)程,直到所有數(shù)據(jù)都被編碼到圖像中。
例子
假設(shè)要隱藏的消息是‘Hii’。
消息是三個(gè)字節(jié),因此,對(duì)數(shù)據(jù)進(jìn)行編碼所需的像素為 3 x 3 = 9??紤]一個(gè) 4 x 3 的圖像,總共有 12 個(gè)像素,這足以對(duì)給定的數(shù)據(jù)進(jìn)行編碼。
[(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 ,其二進(jìn)制等效值為 01001000 。
第 2 步
讀取前三個(gè)像素。
(27, 64, 164), (248, 244, 194), (174, 246, 250)
第 3 步
現(xiàn)在,將像素值更改為奇數(shù)為 1,偶數(shù)為 0,就像在二進(jìn)制等效數(shù)據(jù)中一樣。
例如,第一個(gè)二進(jìn)制數(shù)字是0,第一個(gè) RGB 值是 27 ,它需要轉(zhuǎn)換為偶數(shù),這意味著 26 。類似地,64 被轉(zhuǎn)換為 63 因?yàn)橄乱粋€(gè)二進(jìn)制數(shù)字是1 所以 RGB 值應(yīng)該是奇數(shù)。
因此,修改后的像素為:
(26, 63, 164), (248, 243, 194), (174, 246, 250)
第4步
由于我們必須對(duì)更多數(shù)據(jù)進(jìn)行編碼,因此最后一個(gè)值應(yīng)該是偶數(shù)。同樣,i可以在這個(gè)圖像中進(jìn)行編碼。
通過(guò)執(zhí)行 +1 或 -1 使像素值成為奇數(shù)/偶數(shù)時(shí),我們應(yīng)該注意二進(jìn)制條件。即像素值應(yīng)大于或等于 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)]
解碼
對(duì)于解碼,我們將嘗試找到如何逆轉(zhuǎn)之前我們用于數(shù)據(jù)編碼的算法。
1.同樣,一次讀取三個(gè)像素。前 8 個(gè) RGB 值為我們提供了有關(guān)機(jī)密數(shù)據(jù)的信息,第 9 個(gè)值告訴我們是否繼續(xù)前進(jìn)。
2.對(duì)于前八個(gè)值,如果值為奇數(shù),則二進(jìn)制位為 1 ,否則為 0 。
3.這些位連接成一個(gè)字符串,每三個(gè)像素,我們得到一個(gè)字節(jié)的秘密數(shù)據(jù),這意味著一個(gè)字符。
4.現(xiàn)在,如果第 9 個(gè)值是偶數(shù),那么我們繼續(xù)一次讀取三個(gè)像素,否則,我們停止。
例如
讓我們開(kāi)始一次讀取三個(gè)像素。
考慮我們之前編碼的圖像。
[(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步
我們首先讀取三個(gè)像素:
[(26, 63, 164), (248, 243, 194), (174, 246, 250)
第2步
讀取第一個(gè)值:26,它是偶數(shù),因此二進(jìn)制位是 0 。類似地,對(duì)于 63 ,二進(jìn)制位是 1 ,對(duì)于 164 它是 0 。這個(gè)過(guò)程一直持續(xù)到 8 個(gè) RGB 值。
第 3 步
將所有二進(jìn)制值連接后,我們最終得到二進(jìn)制值:01001000。最終的二進(jìn)制數(shù)據(jù)對(duì)應(yīng)于十進(jìn)制值 72,在 ASCII 中,它代表字符 H 。
第 4 步
由于第 9 個(gè)值是偶數(shù),我們重復(fù)上述步驟。當(dāng)遇到的第 9 個(gè)值是奇數(shù)時(shí),我們停止。
結(jié)果,我們得到了原始信息,即 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 圖像庫(kù),它使我們能夠在 Python 中對(duì)圖像執(zhí)行操作。
程序執(zhí)行

數(shù)據(jù)編碼

數(shù)據(jù)解碼
輸入圖像

輸出圖像

局限性
該程序可能無(wú)法對(duì) JPEG 圖像按預(yù)期處理,因?yàn)?JPEG 使用有損壓縮,這意味著修改像素以壓縮圖像并降低質(zhì)量,因此會(huì)發(fā)生數(shù)據(jù)丟失。
參考
- 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
到此這篇關(guān)于詳解如何使用Python隱藏圖像中的數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Python隱藏圖像數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pandas實(shí)現(xiàn)Dataframe的合并
我們知道,在使用pandas處理數(shù)據(jù)的時(shí)候,往往會(huì)需要合并兩個(gè)或者多個(gè)DataFrame的操作,那么本文就來(lái)介紹一下Pandas實(shí)現(xiàn)Dataframe的合并,感興趣的可以了解一下2021-06-06
python cx_Oracle模塊的安裝和使用詳細(xì)介紹
這篇文章主要介紹了python cx_Oracle模塊的安裝和使用詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02
分享unittest單元測(cè)試框架中幾種常用的用例加載方法
這篇文章主要介紹了unittest單元測(cè)試框架中常用的幾種用例加載方法,幫助大家更好的理解和使用python的unittest測(cè)試模塊,感興趣的朋友可以了解下2020-12-12
Python中使用json.load()和json.loads()加載json數(shù)據(jù)的方法實(shí)例
在python編程中,我們經(jīng)常要用到j(luò)son對(duì)象作為數(shù)據(jù)交換格式,下面這篇文章主要給大家介紹了關(guān)于Python中使用json.load()和json.loads()加載json數(shù)據(jù)的方法實(shí)例,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
Python常見(jiàn)內(nèi)置高階函數(shù)即高階函數(shù)用法
這篇文章主要介紹了Python的三種高階函數(shù)map、filter、reduce,高階函數(shù)就是一個(gè)函數(shù)可以作為參數(shù)傳給另外一個(gè)函數(shù),或者一個(gè)函數(shù)的返回值為另外一個(gè)函數(shù)(若返回值為該函數(shù)本身,則為遞歸),滿足其一則為高階函數(shù),具體內(nèi)容,需要的朋友可以參考下面文章的介紹2021-12-12
Python中用PIL庫(kù)批量給圖片加上序號(hào)的教程
這篇文章主要介紹了Python中用PIL庫(kù)批量給圖片加上序號(hào)的教程,PIL庫(kù)是Python中一個(gè)非常強(qiáng)大的處理圖片的庫(kù),需要的朋友可以參考下2015-05-05
Eclipse中Python開(kāi)發(fā)環(huán)境搭建簡(jiǎn)單教程
這篇文章主要為大家分享了Eclipse中Python開(kāi)發(fā)環(huán)境搭建簡(jiǎn)單教程,步驟簡(jiǎn)潔,一目了然,可以幫助大家快速搭建python開(kāi)發(fā)環(huán)境,感興趣的小伙伴們可以參考一下2016-03-03
python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5信號(hào)與槽的高級(jí)使用技巧(自定義信號(hào)與槽)詳解與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5信號(hào)與槽的高級(jí)知識(shí)(自定義信號(hào)與槽)詳解與實(shí)例,需要的朋友可以參考下2020-03-03
pandas 數(shù)據(jù)實(shí)現(xiàn)行間計(jì)算的方法
今天小編就為大家分享一篇pandas 數(shù)據(jù)實(shí)現(xiàn)行間計(jì)算的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
Python 解決相對(duì)路徑問(wèn)題:"No such file or directory"
這篇文章主要介紹了Python 解決相對(duì)路徑問(wèn)題:"No such file or directory"具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06

