LSB图片隐写(最低有效位隐写)
https://blog.51cto.com/u_15127612/4109760
原理我直接贴个链接吧,就是把比特信息一位一位的藏在每个像素RGB的最低有效位里,反正人眼没那么敏锐,差这么点看不出来,而且像素本身最后一位是有意义的,本来就不是全零或全一,如果不知道具体藏在哪里的人很难识别并提取出隐藏信息来。
隐写
# -*- coding: UTF-8 -*-
# encode.py
from PIL import Image
def plus(str):
# Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
return str.zfill(8)
def get_key(strr):
# 获取要隐藏的文件内容
tmp = strr
# f = file(tmp,"rb")
f = open(tmp, "rb")
str = ""
s = f.read()
for i in range(len(s)):
# 逐个字节将要隐藏的文件内容转换为二进制,并拼接起来
# 1.先用ord()函数将s的内容逐个转换为ascii码
# 2.使用bin()函数将十进制的ascii码转换为二进制
# 3.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
# 4.又由于ascii码转换二进制后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
# print("i: s[i]: tmp:",i ,s[i], tmp)
tmp = s[i]
# tmp = ord(tmp)
tmp = bin(tmp)
str = str + plus(tmp.replace('0b', ''))
f.closed
print("str", str)
return str
def mod(x, y):
return x % y
# str1为载体图片路径,str2为隐写文件,str3为加密图片保存的路径
def func(str1, str2, str3):
im = Image.open(str1)
# 获取图片的宽和高
width = im.size[0]
print("width:" + str(width) + "\n")
height = im.size[1]
print("height:" + str(height) + "\n")
count = 0
# 获取需要隐藏的信息
key = get_key(str2)
keylen = len(key)
for h in range(0, height):
for w in range(0, width):
pixel = im.getpixel((w, h))
a = pixel[0]
b = pixel[1]
c = pixel[2]
if count == keylen:
break
# 下面的操作是将信息隐藏进去
# 分别将每个像素点的RGB值余2,这样可以去掉最低位的值
# 再从需要隐藏的信息中取出一位,转换为整型
# 两值相加,就把信息隐藏起来了
a = a - mod(a, 2) + int(key[count])
# 上面这句是把信息藏在第八位,下面这个是把信息藏在第七位
# a = a - (a % 4) + (2 * int(key[count]))
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
b = b - mod(b, 2) + int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
c = c - mod(c, 2) + int(key[count])
count += 1
if count == keylen:
im.putpixel((w, h), (a, b, c))
break
if count % 3 == 0:
im.putpixel((w, h), (a, b, c))
im.save(str3)
# 原图
old = r"E:/face_recognize/GADA-main/imgs_test/Abdullah_Gul_0001.png"
# 处理后输出的图片路径
new = r"E:/face_recognize/GADA-main/imgs_test/Abdullah_Gul_0001_new.png"
# 需要隐藏的信息
enc = r"E:/face_recognize/GADA-main/imgs_test/test.txt"
func(old, enc, new)
提取
# -*- coding: UTF-8 -*-
# decode.py
from PIL import Image
def plus(str):
# Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
return str.zfill(8)
def put_key(dec, strr):
# 存入隐藏的文件内容
f = open(dec, "w", encoding='utf-8')
for i in range(0, len(strr), 8):
strten = int(strr[i:i+8], 2)
f.write(chr(strten))
def get_key(strr):
# 获取要隐藏的文件内容
tmp = strr
# f = file(tmp,"rb")
f = open(tmp, "rb")
str = ""
s = f.read()
for i in range(len(s)):
# 逐个字节将要隐藏的文件内容转换为二进制,并拼接起来
# 1.先用ord()函数将s的内容逐个转换为ascii码
# 2.使用bin()函数将十进制的ascii码转换为二进制
# 3.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
# 4.又由于ascii码转换二进制后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
tmp = s[i]
# tmp = ord(tmp)
tmp = bin(tmp)
str = str + plus(tmp.replace('0b', ''))
f.closed
print("str", str)
return str
def mod(x, y):
return x % y
# str1为图像路径,str2为解码结果路径,n为密文长度
def func(str1, str2, n):
n *= 8
im = Image.open(str1)
width = im.size[0]
print("width:" + str(width) + "\n")
height = im.size[1]
print("height:" + str(height) + "\n")
count = 0
k = []
# 从图片中提取信息
for h in range(0, height):
for w in range(0, width):
pixel = im.getpixel((w, h))
a = pixel[0]
b = pixel[1]
c = pixel[2]
if count == n:
break
# k[count] = mod(a, 2)
k.append(mod(a, 2))
count += 1
if count == n:
break
# k[count] = mod(b, 2)
k.append(mod(b, 2))
count += 1
if count == n:
break
# k[count] = mod(c, 2)
k.append(mod(c, 2))
count += 1
if count == n:
break
# print(k)
strr =''.join(str(i) for i in k)
# print(strr)
# 把k中的二进制串转为ascii码
put_key(dec, strr)
# 解码图像路径
pic = r"E:/face_recognize/GADA-main/imgs_test/Abdullah_Gul_0001_new.png"
# 需要隐藏的信息
dec = r"E:/face_recognize/GADA-main/imgs_test/result.txt"
# 密文位数
num = 64
func(pic, dec, num)