KeLaAd 2022-10-21 09:11
浏览 53
已结题

LSB隐写视频出现花屏

最近在开发一个视频LSB水印隐写加密的项目,遇到了一些问题。我的思路是 原视频提取帧 保存成图片 然后将水印LSB隐写进图片 再将经过隐写的图片转为视频。但是转出来的视频,再提取帧进行解密出水印的时候,就会出现下图这样的花屏。但是在图片转视频的之前,图片是可以正常解密出水印的。相关代码已经贴在下面了,求解。想过是视频压缩问题,但是已经试过几种视频格式了,包括I,4,2,0格式,仍然没有解决。

img


代码下载
https://pan.baidu.com/s/1kqu9ErnTcc-VkgL-LjWePw?pwd=afyx提取码:afyx

帧转视频




import os
import cv2
import time

img_path = './outimages'
# 随便从其中拿到一张图片来代表视频中图片的尺寸
img = cv2.imread('./outimages/1.bmp')
imgInfo = img.shape
size = (imgInfo[1], imgInfo[0])
# 获得文件夹中图片的数量,从而进行循环生成视频文件
img_nums = len(os.listdir(img_path))
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
# 写入对象 1 file name 2 编码器 3 帧率 4 尺寸大小
videoWrite = cv2.VideoWriter(
os.path.join(img_path,'../', 'videos.avi'), fourcc, 30, size)

# 读取这个文件夹中的每一张图片(按照顺序)然后组合成视频,帧率是每秒 30for i in range(len(os.listdir(img_path))):
    filename = str(i+1) + ".bmp"
    filename = os.path.join(img_path, filename)
    # print(filename)
    img = cv2.imread(filename)
    videoWrite.write(img)


视频转帧


import cv2
import shutil
import os


def video2img(input_path, outpath):
    cap = cv2.VideoCapture(input_path)
    total_frame = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    print('总帧数:', total_frame)

    if not os.path.isdir(outpath):
        os.makedirs(outpath)
    else:
        shutil.rmtree(outpath)
        os.makedirs(outpath)
    counter = 0
    if cap.isOpened():
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            counter += 1
            imgname = "%s.bmp" % str(counter)
            path = os.path.join(outpath, imgname)
            cv2.imwrite(path, frame)
            print(counter)
    cap.release()


video2img('videos.avi', 'testimages')

加密部分


from PIL import Image


def plus(str):
    # 返回指定长度的字符串,原字符串右对齐,前面填充0。
    return str.zfill(8)


def getCode(img):
    str = ""
    # 获取到水印的宽和高进行遍历
    for i in range(img.size[0]):
        for j in range(img.size[1]):

            # 获取水印的每个像素值
            rgb = img.getpixel((i, j))
            # 将像素值转为二进制后保存
            str = str + plus(bin(rgb[0]).replace('0b', ''))
            str = str + plus(bin(rgb[1]).replace('0b', ''))
            str = str + plus(bin(rgb[2]).replace('0b', ''))
            # print(plus(bin(rgb[0]).replace('0b', ''))+"\n")
            # print(plus(bin(rgb[1]).replace('0b', '')) + "\n")
            # print(plus(bin(rgb[2]).replace('0b', '')) + "\n")
    print(str)
    return str


def encry(img, code):
    # 计数器
    count = 0
    countname=0
    # 二进制像素值的长度,可以认为要写入图像的文本长度,提取(解密)时也需要此变量
    codeLen = len(code)
    print(codeLen)

    # 获取到图像的宽、高进行遍历
    for i in range(img.size[0]):
        for j in range(img.size[1]):
            # 获取到图片的每个像素值
            data = img.getpixel((i, j))

            # 如果计数器等于长度,代表水印写入完成
            if count == codeLen:
                break

            # 将获取到的RGB数值分别保存
            r = data[0]
            g = data[1]
            b = data[2]

            """
            下面的是像素值替换,通过取模2得到最后一位像素值(0或1),
            然后减去最后一位像素值,在将code的值添加过来
            """

            r = (r - r % 2) + int(code[count])
            count += 1
            if count == codeLen:
                img.putpixel((i, j), (r, g, b))
                break

            g = (g - g % 2) + int(code[count])
            count += 1
            if count == codeLen:
                img.putpixel((i, j), (r, g, b))
                break

            b = (b - b % 2) + int(code[count])
            count += 1
            if count == codeLen:
                img.putpixel((i, j), (r, g, b))
                break

            # 每3次循环表示一组RGB值被替换完毕,可以进行写入
            if count % 3 == 0:
                img.putpixel((i, j), (r, g, b))

    #countname+=1
    #savename="outimages/%s.bmp" % str(countname)
    #img.save(savename)
    return img


# 获取图像对象
for i in range(1,158):
    imgname = "images/%s.bmp" % str(i)
    savename = "outimages/%s.bmp" % str(i)
    img1 = Image.open(imgname)
    img2 = Image.open('wate1r.bmp')
    # 将图像转换为RGB通道,才能分别获取R,G,B的值
    rgb_im1 = img1.convert('RGB')
    rgb_im2 = img2.convert('RGB')
    # 将水印的像素值转为文本
    code = getCode(rgb_im2)
    # 将水印写入图像
    encry(rgb_im1, code).save(savename)

解密部分


from PIL import Image


def deEncry(img, length):
    # 获取图片的宽和高
    width = img.size[0]
    height = img.size[1]

    # 计数器
    count = 0
    # 结果文本,从图片中提取到的附加值(加密时附加在每个RGB通道后的二进制数值)
    wt = ""

    # 遍历图片
    for i in range(width):
        for j in range(height):
            # 获取像素点的值
            rgb = img.getpixel((i, j))

            # 提取R通道的附加值
            if count % 3 == 0:
                count += 1
                wt = wt + str(rgb[0] % 2)
                if count == length:
                    break

            # 提取G通道的附加值
            if count % 3 == 1:
                count += 1
                wt = wt + str(rgb[1] % 2)
                if count == length:
                    break

            # 提取B通道的附加值
            if count % 3 == 2:
                count += 1
                wt = wt + str(rgb[2] % 2)
                if count == length:
                    break
        if count == length:
            break
    return wt


def showImage(wt):
    str1 = []
    for i in range(0, len(wt), 8):
        # 以每8位为一组二进制,转换为十进制
        str1.append(int(wt[i:i + 8], 2))
    # 图片大于水印图片2个像素,便于对比
    img_out = Image.new("RGB", (802, 47))
    flag = 0
    for m in range(0, 800):
        for n in range(0, 45):
            img_out.putpixel((m, n), (str1[flag], str1[flag + 1], str1[flag + 2]))
            flag += 3
    img_out.show()

length = 864000
#for i in range(1,158):
    #imgname = "outimages/%s.bmp" % str(i)
imgname="testimages/1.bmp"
img = Image.open(imgname)
rgb_im1 = img.convert('RGB')
wt = deEncry(rgb_im1, length)
showImage(wt)
  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 已结题 (查看结题原因) 10月22日
    • 修改了问题 10月21日
    • 修改了问题 10月21日
    • 创建了问题 10月21日

    悬赏问题

    • ¥15 preLaunchTask"C/C++: aarch64- apple-darwin22-g++-14 生成活动 文件”已终止,退出代码为-1。
    • ¥18 关于#贝叶斯概率#的问题:这篇文章中利用em算法求出了对数似然值作为概率表参数,然后进行概率表计算,这个概率表是怎样计算的呀
    • ¥20 C#上传XML格式数据
    • ¥15 elementui上传结合oss接口断点续传,现在只差停止上传和继续上传,各大精英看下
    • ¥100 单片机hardfaulr
    • ¥20 手机截图相片分辨率降低一半
    • ¥50 求一段sql语句,遇到小难题了,可以50米解决
    • ¥15 速求,对多种商品的购买力优化问题(用遗传算法、枚举法、粒子群算法、模拟退火算法等方法求解)
    • ¥100 速求!商品购买力最优化问题(用遗传算法求解,给出python代码)
    • ¥15 虚拟机检测,可以是封装好的DLL,可付费