前言
本文展示论文《基于自适应哈夫曼编码的密文可逆信息隐藏算法》的复现代码。代码块的结构如下:
其中,每个代码块都包含了测试该代码块的功能的主函数代码,使用时可放心运行,前提是你按照这个包结构把文件命名改好,放在同一个文件夹下放好。.idea和__pycache__文件不用管。还有main.py、InformationEmbedding.py也是多余的文件。
论文内容解析请参考本人的这篇文章:
论文简述基于自适应哈夫曼编码的密文可逆信息隐藏算法(基于位图压缩的加密图像可逆信息隐藏算法)_zrc007007的博客-CSDN博客
精简版代码在这里:
论文复现代码《基于自适应哈夫曼编码的密文可逆信息隐藏算法》导演剪辑版-CSDN博客
复现代码
MedianEdgeDetector.py
首先是中值预测器,文件名为MedianEdgeDetector.py:
import numpy as npclass MED:def __init__(self):# 示例数据self.data = [[162, 162, 162, 161, 162, 157, 163, 161],[162, 162, 162, 161, 162, 157, 163, 161],[162, 162, 162, 161, 162, 157, 163, 161],[162, 162, 162, 161, 162, 157, 163, 161],[162, 162, 162, 161, 162, 157, 163, 161],[164, 164, 158, 155, 161, 159, 159, 160],[160, 160, 163, 158, 160, 162, 159, 156],[159, 159, 155, 157, 158, 159, 156, 157]]def detect(self, data):# 中值预测result = np.zeros_like(data)result[0][0] = data[0][0]for i in range(1, len(data)):result[i][0] = data[i][0]result[0][i] = data[0][i]for i in range(1, len(data)):for j in range(1, len(data[0])):a = data[i - 1][j - 1]b = data[i - 1][j]c = data[i][j - 1]if a <= min(b, c):result[i][j] = max(b, c)elif a >= max(b, c):result[i][j] = min(b, c)else:result[i][j] = b + c - areturn resultif __name__ == "__main__":print(MED().detect(MED().data))
AdaptiveHuffmanEncoding.py
对图像进行自适应哈夫曼编码,文件名为AdaptiveHuffmanEncoding.py:
from MedianEdgeDetector import MED
import numpy as np
from math import infclass HuffCode:def compare(self, num1, num2):# 比较像素值的相同比特位数count = 0for i in range(8):divisor = pow(2, 7-i)if int(num1 // divisor) == int(num2 // divisor):count += 1num1 = num1 - divisornum2 = num2 - divisorelse:breakreturn countdef count(self, origindata, data):# 生成图像相同像素值的比特位数的比较结果result = {}resultMap = np.zeros_like(data)resultMap[0][0] = -1for i in range(1, len(data)):resultMap[i][0] = -1resultMap[0][i] = -1for i in range(1, len(data)):for j in range(1, len(data[0])):num = self.compare(origindata[i][j], data[i][j])resultMap[i][j] = numresult[num] = result.get(num, 0) + 1return resultMap, result# 初始化哈夫曼结点
class Huffmannode(object):def __init__(self):self.parent=0self.left=0self.right=0self.weight=0# 选择最小的结点下标
def select_node(huffman):# 俩个结点直接返回不需要找最小俩个结点if len(huffman)==2:return 0,1min=semin=inf# 初始化成无穷大f=s=-1for i in range(len(huffman)):if huffman[i].parent==0:if min>huffman[i].weight:semin=mins=fmin=huffman[i].weightf=ielif semin>huffman[i].weight:semin=huffman[i].weights=ireturn f,s# 编码
def Huffman_code(origin_dict):# 给结点赋权重n=len(origin_dict)m=2*n-1huffman=[]for i in origin_dict:temp_huffmannode=Huffmannode()temp_huffmannode.weight=origin_dict[i]huffman.append(temp_huffmannode)# 构建Huffman树,选择俩个最小的结点合并for i in range(n,m):f,s=select_node(huffman)temp_huffmannode=Huffmannode()temp_huffmannode.weight=huffman[f].weight+huffman[s].weighttemp_huffmannode.right=f # 小的放在右边temp_huffmannode.left=shuffman[f].parent=huffman[s].parent=ihuffman.append(temp_huffmannode)# 0,1编码,右0,左1codeing_dict = dict.fromkeys(origin_dict, None)for i in range(0,n):s=''k=iparent=huffman[i].parentwhile parent!=0:if huffman[parent].left==k:s+='1'k=parentparent=huffman[parent].parentelse:s+='0'k=parentparent=huffman[parent].parentcodeing_dict[list(origin_dict.keys())[i]]=list(reversed(s))for k in codeing_dict.items():codeing_dict[k[0]] = ''.join(k[1])return codeing_dictif __name__ == "__main__":MED = MED()origindata = MED.dataMEDdata = MED.detect(origindata)print(np.array(origindata))print(MEDdata)print(HuffCode().compare(159, 160))resultMap, result = HuffCode().count(origindata, MEDdata)print(result)'''# 输入原始字符集s = input('输入即将被编码的字符:')# 创建字典计算频率dic = {}for i in range(len(s)):# get方法,如果有键返回该键对应的值,如果没键,可以设置返回值dic[s[i]] = dic.get(s[i], 0) + 1'''code_dict = Huffman_code(result)print(code_dict)
Crypting.py
混沌矩阵加密,文件名为Crypting.py:
import numpy as np
from skimage import io
import matplotlib.pyplot as pltdef crypt(im, miu, x0):'''logistic混沌加密:param im: 图像:param miu: μ参数:param x0: x0参数:return: 返回密文图像'''h, w = im.shapec_ = np.zeros_like(im)c_[0][0] = x0c=[]c.append(x0)result = np.zeros_like(im)result[0][0] = (x0 * pow(2, 48)) % 256for x in range(1, h * w):i = x // wj = x % wc.append(miu * c[x - 1] * (1 - c[x - 1]))c_[i][j] = (c[x] * pow(2, 48)) % 256for i in range(h):for j in range(w):result[i][j] = im[i][j] ^ c_[i][j]return resultdef transform(img):column, row = img.shaperesult = np.zeros_like(img, dtype='int_')for i in range(column):for j in range(row):result[i][j] = int(img[i][j] * 255)return resultif __name__ == "__main__":plt.set_cmap(cmap='gray')img = io.imread("../img/lena_grey.tif")print(img)plt.imshow(img)img = transform(img)print(img)plt.figure()enc_img = crypt(img, 3.6, 0.5)plt.imshow(enc_img)plt.figure()dec_img = crypt(enc_img, 3.6, 0.5)plt.imshow(dec_img)plt.show()
LabelMapEmbedding.py
位图嵌入,文件名LabelMapEmbedding.py:
import numpy as np
import math
from AdaptiveHuffmanEncoding import *
from Crypting import *
# from MedianEdgeDetector import *def int2bin(num, leng):'''整数int转二进制格式binTransform a integer to a string whose length is leng.:param num: numbers waiting for transforming:param leng: the length of hoped result string:return: a string of leng length'''if leng < 1:raise Exception("Length isn't positive integer!")place = 1result = ''while place <= leng:result = str(num % 2) + resultnum = num // 2if num == 0:return (leng - place) * '0' + resultplace += 1raise Exception("Length of binary string isn't enough!")def bin2int(string, leng):'''二进制格式bin转整数intTransfer a string of length of leng to a positive integer:param string: string waiting to be transferred:param leng: the length of reading:return: a positive integer less than 2^leng'''if leng < 1:raise Exception("Length isn't positive integer!")if len(string) < leng:raise Exception("Length of string under transferring isn't enough!")place = 1result = 0while place <= leng:result += int(string[place - 1]) * pow(2, leng - place)place += 1return resultdef binstrcomplmt(string, length, complement):'''给二进制格式补位,补到前面。比如补0就给complement传0,补1就传1Complement strings with which we decide.:param string: string waiting to be complemented:param length: what we hope it to length:param complement: using what character to complement it:return: string already complemented'''return (length - len(string)) * complement + stringdef binstrbackcomplmt(string, length, complement):'''给二进制格式补位,补到后面Complement strings with which we decide on its backhand.:param string: string waiting to be complemented:param length: what we hope it to length:param complement: using what character to complement it:return: string already complemented'''return string + (length - len(string)) * complementdef generatec(dict):'''生成嵌入信息中的c1到c8generate c info:param dict: Huffman code diction:return:'''result = ''c = []for i in range(9):c.append(0)c[i] = len(dict.get(i, ''))result += int2bin(c[i], 4)print(c)return resultdef generateh(dict):'''生成嵌入信息中的h1到h8generate h info:param dict: Huffman code diction:return:'''result = ''h = []for i in range(9):h.append('')h[i] = binstrcomplmt(dict.get(i, '0'), 8, '0')result += h[i]print(h)return resultdef countLm(countDict, lenDict):'''生成论文中说的Lm,变成Eta还需要转换一下Counting Lm:param countDict: diction of Huffman codes' appearance:param lenDict: Huffman code diction:return:'''count = 0for i in range(9):count += countDict.get(i, 0) * len(lenDict.get(i, ''))return countdef generatef(Lm, shapeOfImg):'''生成嵌入信息中的fgenerate f, which is Lm's bits' num's binary format:param Lm::param shapeOfImg::return:'''return int2bin(Lm, math.ceil(np.log2(shapeOfImg[0])) + math.ceil(np.log2(shapeOfImg[1])) + 2)def generateEta(dic, labelmap):'''生成嵌入信息中的EtaTransferred label map's binary format:param dic::param labelmap::return:'''result = ''for i in range(1, labelmap.shape[0]):for j in range(1, labelmap.shape[1]):result += dic[labelmap[i][j]]return resultdef generatelabelinfo(HuffDict, CountDict, LabelMap):'''生成总的嵌入信息Generate embedding information of label map:param HuffDict: Huffman code diction:param CountDict: Length of Huffman codes' diction:param LabelMap: The label map:return: Embedding information of label map'''return generatec(HuffDict) + generateh(HuffDict) + generatef(countLm(CountDict,HuffDict), LabelMap.shape)\+ generateEta(HuffDict, LabelMap)def embedinfo(LabelInfo, EncryptedImg, LabelMap, data):# 嵌入位图信息ReferencePixels = ''result = np.array(EncryptedImg)for i in range(EncryptedImg.shape[0]):ReferencePixels += int2bin(EncryptedImg[0][i], 8)result[0][i] = bin2int(LabelInfo, 8)LabelInfo = LabelInfo[8:] # 截掉8个for i in range(1, EncryptedImg.shape[1]):ReferencePixels += int2bin(EncryptedImg[i][0], 8)result[i][0] = bin2int(LabelInfo, 8)LabelInfo = LabelInfo[8:]EmbeddingInfo = LabelInfo + ReferencePixels + dataprint("Length of Reference Pixels is:", len(ReferencePixels))count = 0row = count // (EncryptedImg.shape[1] - 1) + 1column = count % (EncryptedImg.shape[1] - 1) + 1t = LabelMap[row][column]maximum = (EncryptedImg.shape[0] - 1) * (EncryptedImg.shape[1] - 1)while len(EmbeddingInfo) > 0:if 0 <= t <= 6:result[row][column] = EncryptedImg[row][column] % pow(2, 7 - t)\+ bin2int(binstrbackcomplmt(EmbeddingInfo[:t+1], 8, '0'), 8)EmbeddingInfo = EmbeddingInfo[t+1:]elif 7 <= t <= 8:result[row][column] = bin2int(binstrbackcomplmt(EmbeddingInfo[:8], 8, '0'), 8)EmbeddingInfo = EmbeddingInfo[8:]count += 1if count >= maximum:raise Exception("There's no room for embedding!")row = count // (EncryptedImg.shape[1] - 1) + 1column = count % (EncryptedImg.shape[1] - 1) + 1t = LabelMap[row][column]return resultdef detect(data):'''测试用预测函数:param data::return:'''result = np.zeros_like(data)result[0][0] = data[0][0]for i in range(1, len(data)):result[i][0] = data[i][0]result[0][i] = data[0][i]for i in range(1, len(data)):for j in range(1, len(data[0])):a = data[i - 1][j - 1]b = data[i - 1][j]c = data[i][j - 1]if a <= min(b, c):result[i][j] = max(b, c)elif a >= max(b, c):result[i][j] = min(b, c)else:result[i][j] = b + c - areturn resultif __name__ == "__main__":print(128//2)print(128%2)strng = int2bin(1, 8)print(strng)print(bin2int(strng,8))print(bin2int('1', 1))MED = MED()origindata = MED.dataorigindata = np.array(origindata)MEDdata = MED.detect(origindata)print("The origin data is:")print(np.array(origindata))print("The predicted data is:")print(MEDdata)print(HuffCode().compare(159, 160))resultMap, countingResult = HuffCode().count(origindata, MEDdata)print("The label map is:")print(resultMap)print("The counting result of Huffman coding is:", countingResult)'''# 输入原始字符集s = input('输入即将被编码的字符:')# 创建字典计算频率dic = {}for i in range(len(s)):# get方法,如果有键返回该键对应的值,如果没键,可以设置返回值dic[s[i]] = dic.get(s[i], 0) + 1'''code_dict = Huffman_code(countingResult)print(code_dict)generatec(code_dict)print(generatec(code_dict))print(len(generatec(code_dict)))print(generateh(code_dict), len(generateh(code_dict)))lm = countLm(countingResult, code_dict)print("Lm is:", lm)f = generatef(lm, MEDdata.shape)print("f is:", f)print("length of f is:", len(f))Eta = generateEta(code_dict, resultMap)print("The length of Eta is:", len(Eta))print("Eta is:")print(Eta)labelInfo = generatelabelinfo(code_dict,countingResult, resultMap)print("The length of labelInfo is:", len(labelInfo))print("Label info:")print(labelInfo)print("Is length of c, h, f and Eta equals to labelInfo:", len(generatec(code_dict)) + len(generateh(code_dict)) +\len(f) + len(Eta) == len(labelInfo))embedded = embedinfo(labelInfo, crypt(origindata, 3.6, 0.5), resultMap, '0110')print(embedded)strng = int2bin(903, 11)print(strng)print(strng[12:] == '')print(strng[:3])print(detect(origindata))
DataExtractionandImageRecovery.py
数据提取和恢复,文件名DataExtractionandImageRecovery.py:
from LabelMapEmbedding import *
from skimage import io
import matplotlib.pyplot as pltdef HuffDecode(HuffDict, info):# 哈夫曼解码for i in range(9):if info[:len(HuffDict.get(i, ''))] == HuffDict.get(i, -1):print("The i is:", i)print(info[:8])print(HuffDict)return i, len(HuffDict[i])raise Exception("No string matches!")def extractpixel(pixel, t):# 根据t值,恢复像素位数if 0 <= t <= 7:return int2bin(pixel, 8)[:t+1]elif t == 8:return int2bin(pixel, 8)else:raise Exception("T out of range!")def calctcut(t):# 根据t值,返回像素数if 0 <= t <= 7:return t + 1elif t == 8:return 8else:raise Exception("T out of range!")def extract1(encrypted):# 提取第一行、第一列info = ''LenDict = {}HuffDict = {}for i in range(encrypted.shape[0]):info += int2bin(encrypted[0][i], 8)for i in range(1, encrypted.shape[1]):info += int2bin(encrypted[i][0], 8)for i in range(9):LenDict[i] = bin2int(info[:4], 4)info = info[4:]for i in range(9):if LenDict[i] != 0:HuffDict[i] = info[8-LenDict[i]:8]info = info[8:]print(LenDict, HuffDict)return HuffDict, infodef extract_exp(encrypted, HuffDict, info, datalen, Label): # Label是用来测试位图和算出来的是不是一样的,可以删掉# 提取位图LabelMap = np.zeros_like(encrypted)decrypted1 = np.array(encrypted)LmLen = math.ceil(np.log2(encrypted.shape[0])) + math.ceil(np.log2(encrypted.shape[1])) + 2Lm = bin2int(info[:LmLen], LmLen)info = info[LmLen:]infoLen = Lm + ((encrypted.shape[0] - 1) + (encrypted.shape[1] - 1) - 1) * 8 + datalencount = len(info) # 已提取到的信息长度place = 0pursuit = 0gonext = 0count1 = 1while count < infoLen:print("count:", count)print("Info len:", infoLen)print("pursuit:", pursuit)row = place // (encrypted.shape[1] - 1) + 1column = place % (encrypted.shape[1] - 1) + 1print("origin row, column:", row, column)if count1 == 1 and count < Lm:t, CodeLen = HuffDecode(HuffDict, info)print("t is:", t)LabelMap[row][column] = tinfo = info[CodeLen:] + extractpixel(encrypted[row][column], t)count += calctcut(t)place += 1print("step1")print("Is the Label Map equal to the extrated one:", Label[row][column] == t)print("place is:", place)print("count is:", count)else:pursuit = 1count1 = 0if pursuit == 1 and gonext == 0:record = placeprint("\nThe staring of step 2's row and column is:\n", row , column)while place < (encrypted.shape[0] - 1) * (encrypted.shape[1] - 1):row = place // (encrypted.shape[1] - 1) + 1column = place % (encrypted.shape[1] - 1) + 1t, CodeLen = HuffDecode(HuffDict, info)LabelMap[row][column] = tinfo = info[CodeLen:] + extractpixel(encrypted[row][column], t)print("step2")print("Is the Label Map equal to the extrated one:", Label[row][column] == t)print("T is {}, and the Label is {}".format(t, Label[row][column]))print("place:", place)print("row, column:", row, column)place += 1print('haha',place)print("end")place = recordrow = place // (encrypted.shape[1] - 1) + 1column = place % (encrypted.shape[1] - 1) + 1gonext = 1if gonext == 1 and count - Lm < (encrypted.shape[0] - 1) * (encrypted.shape[1] - 1) * 8 + datalen:# print("place:",place)# print("row, column:", row, column)info += extractpixel(encrypted[row][column], LabelMap[row][column])count += calctcut(LabelMap[row][column])# print("infolen:", infoLen)# print("count:", count)# print()place += 1for i in range(encrypted.shape[0]):LabelMap[0][i] = -1decrypted1[0][i] = bin2int(info[:8], 8)info = info[8:]for i in range(1, encrypted.shape[1]):LabelMap[i][0] = -1decrypted1[i][0] = bin2int(info[:8], 8)info = info[8:]data = info[:datalen]return LabelMap, decrypted1, datadef reverse(char):# 反转0和1if char == '0':return '1'elif char == '1':return '0'else:raise Exception("Not 0 or 1!")def detect(data, i, j):'''测试用预测函数:param data::return:'''a = data[i - 1][j - 1]b = data[i - 1][j]c = data[i][j - 1]if a <= min(b, c):result = max(b, c)elif a >= max(b, c):result = min(b, c)else:result = b + c - areturn resultdef recovery(img, LabelMap):# 恢复图像result = np.zeros_like(img)for i in range(img.shape[0]):result[0][i] = img[0][i]for i in range(1, img.shape[1]):result[i][0] = img[i][0]for i in range(1, img.shape[0]):for j in range(1, img.shape[1]):px = detect(result, i, j)t = LabelMap[i][j]if t == 8:result[i][j] = pxelif 0 <= t <= 7:result[i][j] = bin2int(int2bin(px, 8)[:t] + '0' * (8 - t), 8)\+ int(reverse(int2bin(px, 8)[t:t+1])) * pow(2, 7 - t) + img[i][j] % pow(2, 7 - t)else:raise Exception("T out of range!")return resultif __name__ == "__main__":MED = MED()# origindata = MED.dataorigindata = io.imread("../img/lena_grey.tif")origindata = transform(origindata)origindata = np.array(origindata)MEDdata = MED.detect(origindata)print("The origin data is:")print(np.array(origindata))print("The predicted data is:")print(MEDdata)print(HuffCode().compare(159, 160))resultMap, countingResult = HuffCode().count(origindata, MEDdata)print("The label map is:")print(resultMap)print("The counting result of Huffman coding is:", countingResult)code_dict = Huffman_code(countingResult)print(code_dict)generatec(code_dict)print(generatec(code_dict))print(len(generatec(code_dict)))print(generateh(code_dict), len(generateh(code_dict)))lm = countLm(countingResult, code_dict)print("Lm is:", lm)f = generatef(lm, MEDdata.shape)print("f is:", f)print("length of f is:", len(f))Eta = generateEta(code_dict, resultMap)print("The length of Eta is:", len(Eta))print("Eta is:")print(Eta)labelInfo = generatelabelinfo(code_dict,countingResult, resultMap)print("The length of labelInfo is:", len(labelInfo))print("Label info:")print(labelInfo)secret = '0110010000' * 50 # 用于测试的秘密信息embedded = embedinfo(labelInfo, crypt(origindata, 3.6, 0.5), resultMap, secret) # 嵌入秘密信息print(embedded)huff_code, info1 = extract1(embedded)print("The length of rest of info waiting for extracting is:", len(info1))print(int2bin(100, 8))print(extractpixel(100, 0))# resultMap2, decrypted1, data= extract2(embedded, huff_code, info1, 4)resultMap2, decrypted1, data = extract_exp(embedded, huff_code, info1, len(secret), resultMap)print("The encrypted img is:\n", crypt(origindata, 3.6, 0.5))print("The decrypted1 img is:\n", decrypted1)print(resultMap2)print(resultMap)print(data)if secret == data:print("THE extract is successful!")img1 = crypt(decrypted1, 3.6, 0.5)print("img1 is:\n",img1)'''print("Origin:")print(origindata)print("Detect img:")print(detect(img1))print("Detected origin data:")print(detect(origindata))'''res = img1 - origindataprint("result compare with origin data:\n")print(res)img2 = recovery(img1, resultMap2)print(img2)res = img2 - origindataprint("img2 compares to origin:\n", res)plt.set_cmap(cmap='gray')plt.subplot(221)plt.imshow(origindata)plt.title("Origin imagery")plt.subplot(222)plt.imshow(embedded)plt.title("Embedded imagery")plt.subplot(223)plt.imshow(img1)plt.title("Preliminary decrypted imagine")plt.subplot(224)plt.imshow(img2)plt.title("Fully recovered imagine")plt.show()
Comparison.py
计算指标,比较结果,文件名Comparison.py:
import numpy as np
import math
import cv2
from DataExtractionandImageRecovery import *
from skimage.color import rgb2graydef ssim(img1, img2):#计算ssim指标C1 = (0.01 * 255)**2C2 = (0.03 * 255)**2img1 = img1.astype(np.float64)img2 = img2.astype(np.float64)kernel = cv2.getGaussianKernel(11, 1.5)window = np.outer(kernel, kernel.transpose())mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5] # validmu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]mu1_sq = mu1**2mu2_sq = mu2**2mu1_mu2 = mu1 * mu2sigma1_sq = cv2.filter2D(img1**2, -1, window)[5:-5, 5:-5] - mu1_sqsigma2_sq = cv2.filter2D(img2**2, -1, window)[5:-5, 5:-5] - mu2_sqsigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *(sigma1_sq + sigma2_sq + C2))return ssim_map.mean()def psnr(img1, img2):# 计算PSNR指标mse = np.mean( (img1/255. - img2/255.) ** 2 )if mse < 1.0e-10:return 100PIXEL_MAX = 1return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))if __name__ == "__main__":MED = MED()# Baboon 3.6 0.5origindata = io.imread("../img/lena_gray_512.tif")# origindata = rgb2gray(origindata)print(origindata)# origindata = transform(origindata)origindata = np.array(origindata)MEDdata = MED.detect(origindata)resultMap, countingResult = HuffCode().count(origindata, MEDdata)code_dict = Huffman_code(countingResult)labelInfo = generatelabelinfo(code_dict, countingResult, resultMap)encrypted = crypt(origindata, 3.7, 0.9)containingLabel = embedinfo(labelInfo, encrypted, resultMap, '')embedded = embedinfo(labelInfo, encrypted, resultMap, '0110010000')huff_code, info1 = extract1(embedded)# resultMap2, decrypted1, data = extract_exp(embedded, huff_code, info1, 10, resultMap)# img1 = crypt(decrypted1, 3.6, 0.5)print("Lena")print("Comparison of PSNR and SSIM between encrypted imagine and the original:")print("PSNR:", psnr(origindata, encrypted))print("SSIM:", ssim(origindata, encrypted))print()print("Comparison of PSNR and SSIM between containing Label Map imagine and the original:")print("PSNR:", psnr(origindata, containingLabel))print("SSIM:", ssim(origindata, containingLabel))print()print("Comparison of PSNR and SSIM between embedded imagine and the original:")print("(With the secret of '0110010000')")print("PSNR:", psnr(origindata, embedded))print("SSIM:", ssim(origindata, embedded))