图片隐写及隐写分析

本文介绍了图片隐写的基本概念,包括LSB隐写方法及其评价指标,详细讲解了面向JPEG的图像隐写,如Jsteg、F3隐写,并探讨了F3隐写的嵌入容量计算。同时,提到了调色板隐写(EZStego)和BPCS、PVD隐写方法,以及隐写分析中的卡方分析和RS分析。文章提供了部分Python代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

两句闲话

  老师在课上讲了许多图片隐写和隐写分析的方法,在这里我整合一下,并对部分进行代码实现。

LSB隐写

  LSB隐写是最基础、最简单的隐写方法,具有容量大、嵌入速度快、对载体图像质量影响小的特点。

  LSB的大意就是最低比特位隐写。我们将深度为8的BMP图像,分为8个二值平面(位平面),我们将待嵌入的信息(info)直接写到最低的位平面上。换句话说,如果秘密信息与最低比特位相同,则不改动;如果秘密信息与最低比特位不同,则使用秘密信息值代替最低比特位。

  具体实现如下

from PIL import Image
import math

class LSB:
	def __init__(self):
		self.im=None

	def load_bmp(self,bmp_file):
		self.im=Image.open(bmp_file)
		self.w,self.h=self.im.size
		self.available_info_len=self.w*self.h # 不是绝对可靠的
		print ("Load>> 可嵌入",self.available_info_len,"bits的信息")

	def write(self,info):
		"""先嵌入信息的长度,然后嵌入信息"""
		info=self._set_info_len(info)
		info_len=len(info)
		info_index=0
		im_index=0
		while True:
			if info_index>=info_len:
				break
			data=info[info_index]
			x,y=self._get_xy(im_index)
			self._write(x,y,data)
			info_index+=1
			im_index+=1

	def save(self,filename):
		self.im.save(filename)

	def read(self):
		"""先读出信息的长度,然后读出信息"""
		_len,im_index=self._get_info_len()
		info=[]
		for i in range(im_index,im_index+_len):
			x,y=self._get_xy(i)
			data=self._read(x,y)
			info.append(data)
		return info

	#===============================================================#
	def _get_xy(self,l):
		return l%self.w,int(l/self.w)

	def _set_info_len(self,info):
		l=int(math.log(self.available_info_len,2))+1
		info_len=[0]*l
		_len=len(info)
		info_len[-len(bin(_len))+2:]=[int(i) for i in bin(_len)[2:]]
		return info_len+info

	def _get_info_len(self):
		l=int(math.log(self.w*self.h,2))+1
		len_list=[]
		for i in range(l):
			x,y=self._get_xy(i)
			_d=self._read(x,y)
			len_list.append(str(_d))
		_len=''.join(len_list)
		_len=int(_len,2)
		return _len,l

	def _write(self,x,y,data):
		origin=self.im.getpixel((x,y))
		lower_bit=origin%2
		if lower_bit==data:
			pass
		elif (lower_bit,data) == (0,1):
			self.im.putpixel((x,y),origin+1)
		elif (lower_bit,data) == (1,0):
			self.im.putpixel((x,y),origin-1)

	def _read(self,x,y):
		data=self.im.getpixel((x,y))
		return data%2

if __name__=="__main__":
	lsb=LSB()
	# 写
	lsb.load_bmp('test.bmp')
	info1=[0,1,0,1,1,0,1,0]
	lsb.write(info1)
	lsb.save('lsb.bmp')
	# 读
	lsb.load_bmp('lsb.bmp')
	info2=lsb.read()
	print (info2)

  在这里,我们定义几个指标来评价隐写算法。

  假设,某灰度图像的大小为$M\times N$,深度为8。

嵌入容量  $M\times N$bit。

嵌入率   $\frac{嵌入容量}{总容量}$,LSB的嵌入率为$\frac{1}{8}=12.5\%$。

MSE     mean square error,平均方根误差,$MSE=\frac{\sum^{M}_{m=1}\sum^{N}_{n-1}d(m,n)^2}{M \times N}$,这里的$d(m,n)$指的是,原图像和修改后的图像在$(m,n)$位置上的像素点之差。

PSNR   peak signal-to-noise ratio,峰值信噪比,$PSNR=-10log\{\frac{MSE}{255^2MN}\}$。

更多的评价方法还有,VQM(vedio quality measurement), SSIM(structural similarity index)等。

面向JPEG的图像隐写(1):Jsteg隐写

  关于JPEG格式,可以看看这篇博客 JPEG图像压缩算法流程详解。JPEG压缩中,最主要的就是DCT变换。

  Jsteg隐写是将秘密信息嵌入在量化后的DCT系数的LSB上,但原始值为-1,0,+1的DCT系数除外。此外,由于量化后的DCT系数中有负数,编程的时候需要格外注意以下。

  具体实现如下

import math

class Jsteg:
	def __init__(self):
		self.sequence_after_dct=None

	def set_sequence_after_dct(self,sequence_after_dct):
		self.sequence_after_dct=sequence_after_dct
		self.available_info_len=len([i for i in self.sequence_after_dct if i not in (-1,1,0)]) # 不是绝对可靠的
		print ("Load>> 可嵌入",self.available_info_len,'bits')
	
	def get_sequence_after_dct(self):
		return self.sequence_after_dct

	def write(self,info):
		"""先嵌入信息的长度,然后嵌入信息"""
		info=self._set_info_len(info)
		info_len=len(info)
		info_index=0
		im_index=0
		while True:
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值