最低有效位(LSB)隐写术将信息藏在PNG图片中
编解码python脚本
ecode.py 编码脚本:将1000个字母写入到图片中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from PIL import Image
import numpy as np
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def embed_text_in_image(image_path, output_path, text):
img = Image.open(image_path)
img = img.convert('RGBA')
pixels = np.array(img)
text += chr(0) # Add a null character as a terminator
bits = text_to_bits(text)
if len(bits) > pixels.size * 3:
raise ValueError("Text is too long to be embedded in the given image.")
bit_index = 0
for i in range(pixels.shape[0]):
for j in range(pixels.shape[1]):
if bit_index < len(bits):
for k in range(3): # Only modify the RGB channels
if bit_index < len(bits):
pixels[i, j, k] = (pixels[i, j, k] & ~1) | int(bits[bit_index])
bit_index += 1
else:
break
img = Image.fromarray(pixels)
img.save(output_path)
# Example usage
text = "m" + "A" * 998 + "M" # 1000 letters
embed_text_in_image('demo.png', 'demo_embedded.png', text)
展开
decode.py 解码脚本:读取出上段代码中写入字符信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from PIL import Image
import numpy as np
def bits_to_text(bits, encoding='utf-8', errors='ignore'):
n = int(bits, 2)
return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
def extract_text_from_image(image_path):
img = Image.open(image_path)
img = img.convert('RGBA')
pixels = np.array(img)
bits = ''
bit_index = 0
for i in range(pixels.shape[0]):
for j in range(pixels.shape[1]):
for k in range(3): # Only read the RGB channels
bits += str(pixels[i, j, k] & 1)
bit_index += 1
text = bits_to_text(bits)
# Find the null character and strip off any extra bits
null_index = text.find(chr(0))
if null_index != -1:
text = text[:null_index]
return text
# Example usage
extracted_text = extract_text_from_image('demo_embedded.png')
print(extracted_text)
展开
图片相似度验证
因为LSB隐写术是一种对图片有损的写入方法,这里用脚本比较下原图和编码后的图片相似度
以下是一个使用SSIM和MSE来比较两个图片相似度的脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import numpy as np
from skimage.metrics import structural_similarity as ssim
from skimage.io import imread
from skimage.color import rgb2gray
import cv2
def mse(imageA, imageB):
# The 'Mean Squared Error' between the two images is the sum of the squared difference between the two images
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
return err
def compare_images(imageA, imageB):
# If the images have 4 channels (RGBA), convert them to 3 channels (RGB)
if imageA.shape[2] == 4:
imageA = cv2.cvtColor(imageA, cv2.COLOR_RGBA2RGB)
if imageB.shape[2] == 4:
imageB = cv2.cvtColor(imageB, cv2.COLOR_RGBA2RGB)
# Convert the images to grayscale
imageA_gray = rgb2gray(imageA)
imageB_gray = rgb2gray(imageB)
# Compute the mean squared error and structural similarity index
m = mse(imageA_gray, imageB_gray)
s = ssim(imageA_gray, imageB_gray, data_range=imageA_gray.max() - imageA_gray.min())
return m, s
# Load the two input images
imageA = imread('demo.png')
imageB = imread('demo_embedded.png')
# Compare the images
mse_value, ssim_value = compare_images(imageA, imageB)
print(f"Mean Squared Error (MSE): {mse_value}")
print(f"Structural Similarity Index (SSIM): {ssim_value}")
展开
MSE(均方误差):计算两张图片之间像素差的平方平均值。值越低,图片越相似。
SSIM(结构相似性指数):衡量两张图片的结构相似度,值在-1到1之间,值越高,图片越相似。
运行脚本得到相似度结果:
1
2
Mean Squared Error (MSE): 6.036087972159335e-09
Structural Similarity Index (SSIM): 0.9999990593112368
展开
6.036087972159335e-09是科学计数法,意思是6.036087972159335乘以10的负9次方
作为对比,两张相同的图片结果是
1
2
Mean Squared Error (MSE): 0.0
Structural Similarity Index (SSIM): 1.0
展开
本文由作者按照 CC BY 4.0 进行授权