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()
Пример #2
0
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()
Пример #3
0
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()
Пример #4
0
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()