LSB最低有效位数字水印嵌入算法 含源码

LSB最低有效位数字水印嵌入算法 

本篇博客主要介绍了基于OpenCV的信息隐藏技术,通过在载体图像中嵌入文字信息,生成水印图像,并提供解密方法还原隐藏的信息。

算法介绍:

LSB隐写(最低有效位的隐写),是指通过改变图片中像素的最低位来实现信息的隐藏的。这种隐写方式需要图片是无压缩的位图,因此一般用于bmp和png图片。

加密过程与解密过程:

思路

  1. 创建一个单通道的灰度图像作为载体图像。
  2. 初始化参数,包括字体、缩放比例和文字位置等。
  3. 在载体图像上使用指定的字体和参数写入黑色文字。
  4. 创建水印图像并调整大小为与载体图像相同的尺寸。
  5. 遍历载体图像和水印图像的每个像素点,根据最后一位的奇偶性改变载体图像的像素值,从而嵌入水印信息。
  6. 保存生成的水印图像。
  7. 提供解密方法,遍历水印图像的每个像素点,根据像素值的奇偶性还原隐藏的信息。
  8. 保存解密后的图像。

函数设计

  1. convert_last_bit:将载体图像像素值根据水印图像的像素值的奇偶性进行调整,用于信息嵌入。

        #如果是用==0 或者 ==255 判断会导致字符边缘虚化
        #根据10进制数值是单数 2进制最后一位是1 否则是0
        #通过+1 -1 对数值进行更改 实现信息隐写

    参数:

    • a: 载体图像的像素值
    • b: 水印图像的像素值
    • 返回值:调整后的像素值
      def convert_last_bit(a, b):
      	
      	if b <100 and a % 2 == 1:
      		a = a - 1
      	if b >200 and a % 2 == 0:
      		a = a + 1
      	return a

  2. create_image_with_text:创建带有指定文字的灰度图像。
    这个函数用于创建一个灰度图像,并在图像上嵌入指定的文字。函数首先创建一个尺寸为(400, 400)的灰度图像,像素值初始化为255(白色)。然后,根据函数参数设定了字体类型、缩放比例和线条粗细度。接下来,通过调用cv2.getTextSize()函数获取指定文字的尺寸大小。然后,根据图像和文字尺寸的计算,确定文字在图像上的起始位置坐标。最后,使用cv2.putText()函数将黑色文字嵌入到图像中,生成带有文字的灰度图像,并保存为文件2.png。最后,返回生成的灰度图像。

    参数:

    • text: 要嵌入的文字信息 返回值:生成的灰度图像
      import cv2
      import numpy as np
      
      def create_image_with_text(text):
          # 创建一个尺寸为(400, 400)、像素值为255(白色)的灰度图像
          image = np.full((400, 400), 255, dtype=np.uint8)
          
          # 初始化参数
          font_face = cv2.FONT_HERSHEY_SIMPLEX  # 使用字体类型:OpenCV内置字体cv2.FONT_HERSHEY_SIMPLEX
          font_scale = 1.5  # 字体缩放比例
          thickness = 4  # 文字线条的粗细度
          
          # 获取文字的尺寸大小
          text_size, _ = cv2.getTextSize(text, font_face, font_scale, thickness)
          
          # 计算文字在图像上的起始位置坐标
          origin_x = (image.shape[1] - text_size[0]) // 3
          origin_y = (image.shape[0] + text_size[1]) // 2
          
          # 在图像上写入黑色文字
          cv2.putText(image, text, (origin_x, origin_y), font_face, font_scale, 0, thickness)
          
          # 将生成的图像保存为文件
          cv2.imwrite("2.png", image)
          
          # 返回生成的灰度图像
          return image
      

  3. generate:生成带有水印的图像。
    这个函数用于生成带有水印的图像。函数首先创建一个大小与载体图像相同的全零图像zero_img,用于存储生成的水印图像。然后,调用create_image_with_text函数生成水印图像watermark_img。接下来,根据载体图像和水印图像的尺寸差异,调整水印图像的大小,使其与zero_img图像大小相同。然后,使用双线性插值法将水印图像进行调整。接着,通过遍历载体图像的每个像素点,获取当前像素点的载体图像和水印图像的像素值。最后,将载体图像的最后一位比特位替换为水印图像的像素值,并将结果存入zero_img图像中。最后,将生成的水印图像保存为文件watermarked_img.png,并打印提示信息。
    参数:

    • carry_img: 载体图像,灰度图像
    • msg: 要嵌入的文字信息 功能:根据载体图像和文字信息生成水印图像,并将水印信息嵌入载体图像中
      def generate(carry_img, msg):
          # 创建一个全零图像,尺寸与载体图像相同,用于存储生成的水印图像
          zero_img = np.zeros((carry_img.shape[0], carry_img.shape[1]), dtype=np.uint8)
          
          # 调用create_image_with_text函数生成水印图像
          watermark_img = create_image_with_text(msg)
          
          # 调整水印图像大小,使其与zero_img图像大小相同
          resize_scale_x = int(carry_img.shape[0] / watermark_img.shape[0])
          resize_scale_y = int(carry_img.shape[1] / watermark_img.shape[1])
          resized_watermark_img = cv2.resize(watermark_img, (0, 0), fx=resize_scale_x, fy=resize_scale_y)
          
          # 遍历载体图像的每个像素点
          for i in range(carry_img.shape[0]):
              for j in range(carry_img.shape[1]):
                  # 获取当前像素点的载体图像和水印图像的像素值
                  carry_pixel = carry_img[i, j]
                  watermark_pixel = resized_watermark_img[i, j]
                  
                  # 将载体图像的最后一位比特位替换为水印图像的像素值,并将结果存入zero_img图像中
                  zero_img[i][j] = convert_last_bit(carry_pixel, watermark_pixel)
          
          # 将生成的水印图像保存为文件
          cv2.imwrite('watermarked_img.png', zero_img)
          
          # 打印提示信息
          print('水印图片已生成')
      

  4. decrypt:解密水印图像还原隐藏的信息。
    这个函数用于解密带有水印的图像。函数首先创建一个大小与水印图像相同的全零图像zero_img,用于存储解密后的图像。然后,通过遍历水印图像的每个像素点,获取当前像素点的水印图像的像素值。接下来,判断当前像素值的最后一位比特位是0还是1,如果是0,则将该像素值设为0,否则设为255。然后,将处理后的像素值存入zero_img图像中。最后,将解密后的图像保存为文件decrypt.png,并打印提示信息。
    参数:

    • watermarked_img: 带有水印的图像,灰度图像 功能:根据水印图像的像素值奇偶性,还原隐藏的信息并生成解密后的图像
      def decrypt(watermarked_img):
          # 创建一个全零图像,尺寸与水印图像相同,用于存储解密后的图像
          zero_img = np.zeros((watermarked_img.shape[0], watermarked_img.shape[1]), dtype=np.uint8)
          
          # 遍历水印图像的每个像素点
          for i in range(watermarked_img.shape[0]):
              for j in range(watermarked_img.shape[1]):
                  # 获取当前像素点的水印图像的像素值
                  ij_pixel = watermarked_img[i][j]
                  
                  # 判断当前像素值的最后一位比特位是0还是1,如果是0,则将该像素值设为0,否则设为255
                  if ij_pixel % 2 == 0:
                      ij_pixel = 0
                  else:
                      ij_pixel = 255
                  
                  # 将处理后的像素值存入zero_img图像中
                  zero_img[i][j] = ij_pixel
          
          # 将解密后的图像保存为文件
          cv2.imwrite('decrypt.png', zero_img)
          
          # 打印提示信息
          print('解密图片已生成')
      

源码(单通道灰度图)

import datetime

import cv2
import numpy as np


def convert_last_bit(a, b):
	#如果是用==0 或者 ==255 判断会导致字符边缘虚化
	#根据10进制数值是单数 2进制最后一位是1 否则是0
	#通过+1 -1 对数值进行更改 实现信息隐写
	if b <100 and a % 2 == 1:
		a = a - 1
	if b >200 and a % 2 == 0:
		a = a + 1
	return a


def create_image_with_text(text):
    # 创建一个单通道(灰度)的图像
    image = np.full((400, 400), 255, dtype=np.uint8)
    # 初始化参数
    font_face = cv2.FONT_HERSHEY_SIMPLEX
    font_scale = 1.5
    thickness = 4
    text_size, _ = cv2.getTextSize(text, font_face, font_scale, thickness)
    origin_x = (image.shape[1] - text_size[0]) // 3
    origin_y = (image.shape[0] + text_size[1]) // 2
    # 在图像上写入黑色文字
    cv2.putText(image, text, (origin_x, origin_y), font_face, font_scale, 0, thickness)
    cv2.imwrite("2.png",image)
    return image




def generate(carry_img, msg):
	zero_img = np.zeros((carry_img.shape[0], carry_img.shape[1]), dtype=np.uint8)
	watermark_img = create_image_with_text(msg)
	# 调整水印图片大小与zero_img相同
	resize_scale_x = int(carry_img.shape[0] / watermark_img.shape[0])
	resize_scale_y = int(carry_img.shape[1] / watermark_img.shape[1])
	resized_watermark_img = cv2.resize(watermark_img, (0, 0), fx=resize_scale_x, fy=resize_scale_y)


	for i in range(carry_img.shape[0]):
		for j in range(carry_img.shape[1]):
			# 获取载体图像和水印图像的像素值
			carry_pixel = carry_img[i, j]
			watermark_pixel = resized_watermark_img[i, j]
			zero_img[i][j] = convert_last_bit(carry_pixel, watermark_pixel)
	cv2.imwrite('watermarked_img.png', zero_img)
	print('水印图片已生成')


def decrypt(watermarked_img):
	zero_img = np.zeros((watermarked_img.shape[0], watermarked_img.shape[1]), dtype=np.uint8)
	for i in range(watermarked_img.shape[0]):
		for j in range(watermarked_img.shape[1]):
			# 获取载体图像和水印图像的像素值
			ij_pixel = watermarked_img[i][j]
			if ij_pixel % 2 == 0:
				ij_pixel = 0
			else:
				ij_pixel = 255
			zero_img[i][j] = ij_pixel
	cv2.imwrite('decrypt.png', zero_img)
	print('解密图片已生成')


# 交互式调用
carry_img_path = input("请输入载体图像的路径:")
msg = input("请输入要嵌入的文字信息:")

# 加载载体图像
carrier_image = cv2.imread(carry_img_path, 0)

# 生成水印图像
generate(carrier_image, msg)

# 解密水印图像
watermarked_img_path = "watermarked_img.png"
watermarked_image = cv2.imread(watermarked_img_path, 0)
decrypt(watermarked_image)
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

源码(RGB图片B通道加密黑白水印)

import cv2
import numpy as np


def convert_last_bit(a, b):
    if b < 120 and a % 2 == 1:
        a = a - 1
    if b > 120 and a % 2 == 0:
        a = a + 1
    return a


def create_image_with_text(text):
    # 创建一个三通道(RGB)的图像
    image = np.full((400, 400, 3), 255, dtype=np.uint8)
    # 初始化参数
    font_face = cv2.FONT_HERSHEY_SIMPLEX
    font_scale = 1.5
    thickness = 4
    text_size, _ = cv2.getTextSize(text, font_face, font_scale, thickness)
    origin_x = (image.shape[1] - text_size[0]) // 3
    origin_y = (image.shape[0] + text_size[1]) // 2
    # 在图像上写入黑色文字
    cv2.putText(image, text, (origin_x, origin_y), font_face, font_scale, (0, 0, 0), thickness)
    cv2.imwrite("2.png", image)
    return image


def generate(carry_img, msg):
    zero_img = np.zeros((carry_img.shape[0], carry_img.shape[1], 3), dtype=np.uint8)
    watermark_img = create_image_with_text(msg)
    resized_watermark_img = cv2.resize(watermark_img, (carry_img.shape[1], carry_img.shape[0]))
    for i in range(carry_img.shape[0]):
        for j in range(carry_img.shape[1]):
            # 获取载体图像和水印图像的像素值
            carry_pixel = carry_img[i, j]
            watermark_pixel = resized_watermark_img[i, j]

            # 将B颜色通道的最后一位与水印像素值进行加密
            zero_img[i][j][0] = convert_last_bit(carry_pixel[0], watermark_pixel[0])

            # 其他颜色通道保持不变
            zero_img[i][j][1] = carry_pixel[1]
            zero_img[i][j][2] = carry_pixel[2]

    cv2.imwrite('watermarked_img.png', zero_img)
    print('水印图片已生成')


def decrypt(watermarked_img):
    zero_img = np.zeros((watermarked_img.shape[0], watermarked_img.shape[1]), dtype=np.uint8)
    for i in range(watermarked_img.shape[0]):
        for j in range(watermarked_img.shape[1]):
            # 获取载体图像和水印图像的像素值
            ij_pixel = watermarked_img[i][j][0]
            # 解密B颜色通道的最后一位
            if ij_pixel % 2 == 0:
                ij_pixel = 0
            else:
                ij_pixel = 255

            # 其他颜色通道保持不变
            zero_img[i][j] = ij_pixel

    cv2.imwrite('decrypt.png', zero_img)
    print('解密图片已生成')


# 交互式调用
carry_img_path = input("请输入载体图像的路径:")
msg = input("请输入要嵌入的文字信息:")

# 加载载体图像
carrier_image = cv2.imread(carry_img_path)

# 生成水印图像
generate(carrier_image, msg)

# 解密水印图像
watermarked_img_path = "watermarked_img.png"
watermarked_image = cv2.imread(watermarked_img_path)
decrypt(watermarked_image)

总结:

全靠GPT:albge.aichatos.com/#/chat/1690172938143

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值