def FragileWaterMark_LSBHide(baseimg_dir, saveimg_dir): ''' 基于LSB+奇偶校验的脆弱水印算法-隐藏函数,替换待加入水印图像的最低比特位为奇偶校验 input: baseimg_dir:待加入数字水印的图片 ''' #加载并显示原图 gtimg = Image.open(baseimg_dir) #读入图像 gtimg = gtimg.resize((256, 256), Image.BILINEAR) #width=256, height=256,使用双线性插值 gtimg = gtimg.convert('L') #彩色图像转灰度图像 plt.subplot(1, 2, 1) #将原图显示在一行二列中的第一行第一列 plt.imshow(gtimg, cmap='gray') plt.title('嵌入脆弱数字水印前') plt.xticks([]) plt.yticks([]) a = data_utils.RGB2Gray( baseimg_dir) #将载体图片转化为256*256的列表,其中列表每个位置都是8bit的二进制串 #脆弱水印算法核心,最低比特位存储前七个比特位的奇偶校验位 for i in range(256): for j in range(256): #把a[i][j][0-6]计数1的个数,如果为奇数a[7]=0 否则a[7]=1, count = 0 for k in range(7): if a[i][j][k] == '1': count += 1 if count % 2 != 0: a[i][j] = a[i][j][0:7] + str(1) else: a[i][j] = a[i][j][0:7] + str(0) #将256*256列表中每个位置的8bit串转化为0-255的数字,仍保持256*256大小 temp = [] ttemp = [] summ = 0 for i in range(256): for j in range(256): for k in range(8): summ += int(a[i][j][k]) * math.pow(2, 7 - k) temp.append(int(summ)) summ = 0 ttemp.append(temp) temp = [] #保存并显示嵌入数字水印后的图像 array0 = np.array(ttemp) pimg0 = Image.fromarray(array0) pimg0 = pimg0.convert("L") pimg0.save(saveimg_dir + "watermark.bmp") plt.subplot(1, 2, 2) plt.imshow(pimg0, cmap='gray') plt.title('嵌入脆弱数字水印后') plt.xticks([]) plt.yticks([]) plt.show()
def LSB_Hide(baseimg_dir, hideimg_dir, saveimg_dir): ''' 使用LSB算法的嵌入程序,将待隐藏图片嵌入载体中,显示嵌入前后图片,并保存嵌入后图片 input: baseimg_dir:载体图像的地址 hideimg_dir:待隐藏图片的地址 saveimg_dir:隐藏后图片要保存到的目录 ''' #读入并显示嵌入前图像 gtimg = Image.open(baseimg_dir) #读入图像 gtimg = gtimg.resize((256, 256), Image.BILINEAR) #width, height,使用双线性插值 gtimg = gtimg.convert('L') #彩色图像转灰度图像 plt.subplot(1, 2, 1) #原图显示在第一行第一个 plt.imshow(gtimg, cmap='gray') plt.title('LSB信息隐藏前') plt.xticks([]) plt.yticks([]) a = data_utils.RGB2Gray( baseimg_dir) #将载体图片转化为256*256的列表,其中列表每个位置都是8bit的二进制串 c = data_utils.RGB2Bin(hideimg_dir) #将待隐藏图片转化为256*256的列表,其中每个位置是0或1(二值图像) #LSB信息隐藏算法核心,替换掉最低有效位 #修改代码可以达到其他位平面替换 for i in range(256): for j in range(256): a[i][j] = a[i][j][0:7] + str(int(c[i][j])) #最低位信息隐藏 #a[i][j] = str(int(c[i][j])) + a[i][j][1:8] #最高位信息隐藏 #将256*256列表中每个位置的8bit串转化为0-255的数字,仍保持256*256大小 temp = [] ttemp = [] summ = 0 for i in range(256): for j in range(256): for k in range(8): summ += int(a[i][j][k]) * math.pow(2, 7 - k) temp.append(int(summ)) summ = 0 ttemp.append(temp) temp = [] array0 = np.array(ttemp) #从数组中恢复图片 pimg0 = Image.fromarray(array0) pimg0 = pimg0.convert("L") pimg0.save(saveimg_dir + "cang.bmp") plt.subplot(1, 2, 2) #隐藏后的图片显示在第一行第二个 plt.imshow(pimg0, cmap='gray') plt.title('LSB信息隐藏后') plt.xticks([]) plt.yticks([]) plt.show()
def DCT_Extract(img_dir): ''' 基于DCT的隐藏信息提取 input: img_dir:待提取图像的地址 ''' after_hide = data_utils.RGB2Gray( img_dir) #将载体图片转化为256*256的列表,其中列表每个位置都是0-255(灰度) #将256*256图像裁剪为32*32=1024个8*8的块 temp = [] for i in range(0, 32): for j in range(0, 32): temp.append(after_hide[i * 8:i * 8 + 8, j * 8:j * 8 + 8]) #这里提取的时候还要先DCT变换过去,之后比的是DCT系数 #对1024个块每个块进行dct变化 for i in range(1024): temp[i] = cv2.dct(temp[i]) #进行隐藏信息的提取,比较每个块中5,2 和4,3两个dct变换后数值的大小,重构32*32的二值图像 #(5,2)处大于(4,3)处,嵌入的是1 #(5,2)处小于(4,3)处,嵌入的是0 changtemp = [] chang = [] for i in range(32): for j in range(32): #攻击的时候可能会有等于,怎么说 if temp[i * 32 + j][5][2] >= temp[i * 32 + j][4][3]: changtemp.append(int(1)) elif temp[i * 32 + j][5][2] < temp[i * 32 + j][4][3]: changtemp.append(int(0)) chang.append(changtemp) changtemp = [] #显示提取后的隐藏图片 arrayy2 = np.array(chang) #print(arrayy2.shape) print(arrayy2) pimg2 = Image.fromarray(arrayy2) pimg2 = pimg2.convert("L") plt.subplot(1, 4, 3) plt.imshow(pimg2, cmap='gray') plt.title(u'提取出的水印') plt.xticks([]) plt.yticks([]) plt.show()
def DCT_Hide(baseimg_dir, hideimg_dir, saveimg_dir): ''' 基于DCT的信息隐藏,其中hideimg是baseimg的1/64,因为base图片的8*8个块才能隐藏1bit信息 input: baseimg_dir:载体图像的地址 hideimg_dir:待隐藏图片的地址 saveimg_dir:隐藏后图片要保存到的目录 ''' arr_base = data_utils.RGB2Gray( baseimg_dir) #将载体图片转化为256*256的列表,其中列表每个位置都是0-255(灰度) arr_hide = data_utils.RGB2Bin( hideimg_dir) #将带隐藏图片转化为32*32的列表,其中列表每个位置是0或1(二值) #将原有的256*256图像裁剪为32*32=1024个8*8的块 temp = [] for i in range(0, 32): for j in range(0, 32): temp.append(arr_base[i * 8:i * 8 + 8, j * 8:j * 8 + 8]) #对每个8*8的块使用cv2模块中的dct函数进行dct变换 for i in range(1024): temp[i] = cv2.dct(temp[i]) #进行信息的隐藏,由于要隐藏的图片已经转化为了32*32的二值,所以在每个8*8块中隐藏1bit #选取5,2 4,3两个点 #如果要嵌入的是1,(5,2)处大于(4,3)处 #如果要嵌入的是0,(5,2)处小于(4,3)处 for i in range(32): for j in range(32): #如果要嵌入的是0 if arr_hide[i][j] == 0.0: if temp[i * 32 + j][5][2] > temp[i * 32 + j][4][3]: #如果5,2大于4,3则交换 tt = temp[i * 32 + j][4][3] temp[i * 32 + j][4][3] = temp[i * 32 + j][5][2] temp[i * 32 + j][5][2] = tt elif temp[i * 32 + j][5][2] == temp[i * 32 + j][4][3]: #如果5,2等于4,3则5,2处-= 1 temp[i * 32 + j][5][2] -= 1 #如果要嵌入的是1 else: if temp[i * 32 + j][5][2] < temp[i * 32 + j][4][3]: #如果5,2小于4,3则交换 tt = temp[i * 32 + j][5][2] temp[i * 32 + j][5][2] = temp[i * 32 + j][4][3] temp[i * 32 + j][4][3] = tt elif temp[i * 32 + j][5][2] == temp[i * 32 + j][4][3]: #如果5,2等于4,3则5,2处+= 1 temp[i * 32 + j][5][2] += 1 #对1024个8*8的块进行逆dct变换 for i in range(1024): temp[i] = cv2.idct(temp[i]) #把拆分后的图重新组合起来 #先组合行,再组合列 #组合开始的时候要先各自组合一轮,以便于后续组合 #组合第一行 c = temp[0] for i in range(1, 32): c = np.concatenate((c, temp[i]), axis=1) #组合第二行 b = temp[32] for i in range(33, 64): b = np.concatenate((b, temp[i]), axis=1) #组合第三行,并再将第三行和之前一二行的组合组合,直到结束 for i in range(64, 1024): if i % 32 == 0: c = np.concatenate((c, b), axis=0) b = temp[i] else: b = np.concatenate((b, temp[i]), axis=1) c = np.concatenate((c, b), axis=0) #将组合后的图像保存,作为含秘载体 pimg0 = Image.fromarray(c) pimg0 = pimg0.convert("L") pimg0.save(saveimg_dir + "cang.bmp")
def FragileWaterMark_LSBExtract(img_dir): ''' 基于LSB+奇偶校验的脆弱水印算法-水印提取函数,提取加入的水印检测是否遭到篡改,并显示遭到篡改的区域 input: img_dir:待提取数字水印的图片(可能遭遇攻击) ''' #读入待提取图片并显示 img = Image.open(img_dir) plt.subplot(1, 4, 1) plt.imshow(img, cmap='gray') plt.title('Watermark Image') plt.xticks([]) plt.yticks([]) ttemp = data_utils.RGB2Gray( img_dir) #将待提取图片转化为256*256的列表,其中列表每个位置都是8bit的二进制串 #提取出最低比特位的图片,并显示 t_img = [] img1 = [] for i in range(256): for j in range(256): t_img.append(int(ttemp[i][j][7]) * math.pow(2, 7 - 7)) img1.append(t_img) t_img = [] arrayy = np.array(img1) pimg = Image.fromarray(arrayy) pimg = pimg.convert("L") plt.subplot(1, 4, 2) plt.imshow(pimg, cmap='gray') plt.title(u'直接提取得到的水印') plt.xticks([]) plt.yticks([]) #依据0-6角标处位平面,计算出应有的数字水印 tt_img = [] img2 = [] for i in range(256): for j in range(256): #把a[i][j][0-6]计数,如果为奇数a[7]=0 否则a[7]=1, count = 0 for k in range(7): if ttemp[i][j][k] == '1': count += 1 if count % 2 != 0: tt_img.append(int(1)) else: tt_img.append(int(0)) img2.append(tt_img) tt_img = [] arrayy2 = np.array(img2) pimg2 = Image.fromarray(arrayy2) pimg2 = pimg2.convert("L") plt.subplot(1, 4, 3) plt.imshow(pimg2, cmap='gray') plt.title(u'计算得到的水印') plt.xticks([]) plt.yticks([]) #比较直接提取得到的水印,和通过计算得到的水印,判断是否遭遇篡改 flag = 1 showimg = Image.new("RGB", (256, 256)) #创建一张新的256*256的图,来标出遭遇篡改的区域 arr = np.array(showimg) for i in range(256): for j in range(256): #如果遭遇篡改,将对应位置处角标设置为红色(255,0,0) if arrayy[i][j] != arrayy2[i][j]: flag = 0 arr[i][j][0] = 255 if flag: print("未检测到遭遇篡改") else: print("检测到遭遇篡改!") #如果检测到遭遇篡改,就打出这张图片 pimg3 = Image.fromarray(arr) plt.subplot(1, 4, 4) plt.imshow(pimg3) plt.title(u'检测到的篡改区域') plt.xticks([]) plt.yticks([]) plt.show()