精华内容
下载资源
问答
  • OpenCV数字水印(基于Python)

    千次阅读 2020-06-14 00:18:31
    最近在阅读OpenCV相关书籍,看到数字水印这个技巧觉得很有意思,于是想分享给大家。 ...

    最近在阅读OpenCV相关书籍,看到数字水印这个技巧觉得很有意思,于是想分享给大家。

    前言

    每张图片都是由很多个像素点构成的。在本文中我们采用的载体图像为灰度图,即该图像是一个二维矩阵,其中每个像素点均为8位二进制数,取值范围从00000000(0)-11111111(255)。水印图像为二值图像,即每个像素点只有0和255两个值,其中0代表黑色,255代表白色。

    什么是数字水印

    数字水印即为最低有效位信息隐藏,指的是将一个需要隐藏的二值图像信息嵌入载体图像的最低有效位,即将载体图像的最低有效位层替换为当前需要隐藏的二值图像,从而实现将二值图像隐藏的目的。由于二值图像处于载体图像的最低有效位上,所以对于载体图像的影响并不明显,其具有较高的隐蔽性。

    在必要时直接将载体图像的最低有效位层提取出来,即可得到嵌入在该位上的二值图像,达到提取秘密信息的目的。

    下面我们以一个案例讲解一下二值图像的信息隐藏和提取。

    案例

    1. 源图展示

    本文用到的载体图是lena.bmp
    载体图 lena.bmp
    本文用到的二值水印图是watermark.bmp
    二值水印图 watermark.bmp
    这两张图片的大小相同,即拥有相同数量的像素点。

    2. 图像独取与预处理

    lena=cv2.imread("lena.bmp",0) #读取原始载体图像
    watermark=cv2.imread("watermark.bmp",0) #读取水印图像
    w=watermark[:,:]>0 
    watermark[w]=1 #将水印内的255处理为1,以方便嵌入
    r,c=lena.shape #读取原始载体图像的shape值
    

    这部分代码比较简单,就是独取图像过程。因为水印图像是一个二值图像,即每一个像素点只有0和255两个值,所以我们把大小为255的像素点赋值为1,即每个元素的值均为0000000000000001,以方便后续嵌入。

    3. 嵌入过程

    t254=np.ones((r,c),dtype=np.uint8)*254 #生成内部值都是254的数组
    lenaH7=cv2.bitwise_and(lena,t254) #获取lena图像的高7位
    e=cv2.bitwise_or(lenaH7,watermark) #将watermark嵌入到lenaH7内
    

    第一行语句我们生成了一个r×c的数组t254,数组中的每一个值都为254,即11111110

    第二行语句我们将得到的数组与载体图像进行“与”操作,“与”操作的特点是“有0则为0,无0则为1”。在cv2.bitwise_and(lena,t254)这条语句中,它会将lena与t254中对应位置像素点一一进行“与”操作。由于t254数组中每个元素的高7位均为1,最低位为0,于是相与之后lena中每个元素的高7位得到保留,最低位为0。将得到的结果赋给lenaH7,其中每个元素的值均为xxxxxxx0

    第三行语句我们将得到的lenaH7与步骤二中预处理之后的水印矩阵进行“或”操作,“或”操作的特点是“有1则为1,无1则为0”。在cv2.bitwise_or(lenaH7,watermark)这条语句中,它会将lenaH7与watermark中对应位置像素点一一进行“或”操作。由于lenaH7中每一个元素的最低位均为0,而watermark中每一个元素值均为0000000000000001,于是相或之后lenaH7中每个元素的高7位得到保留,最低位的值即为watermark的值,于是就实现了嵌入过程。将得到的结果赋给e。

    4. 提取过程

    t1=np.ones((r,c),dtype=np.uint8) #生成内部值都是1的数组
    wm=cv2.bitwise_and(e,t1) #从载体图像内,提取水印图像
    w=wm[:,:]>0
    wm[w]=255 #将水印内的1处理为255以方便显示
    

    第一行语句我们生成了一个r×c的数组t1,数组中的每一个值都为1,即为00000001

    第二行语句我们将过程三中得到的e与t1进行“与”操作。由于t1中每一个元素高7位是0,最低位是1,所以相与之后e中每个元素的高7位置0,最低位得到保留,得到的结果赋给wm,wm即为预处理后的水印矩阵。

    第三、四行语句我们将大小为1的元素赋值为255,即完成了水印图像的提取过程。

    5. 显示

    cv2.imshow("lena",lena)
    cv2.imshow("watermark",watermark*255)   #当前watermark内最大值为1
    cv2.imshow("e",e)
    cv2.imshow("wm",wm)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    在这里插入图片描述
    lena是载体图像,watermark是水印图像。
    在这里插入图片描述
    e是lena嵌入水印后的的含水印载体图像,wm是从水印载体图像中提取到的水印图像wm。

    6. 完整代码

    import cv2
    import numpy as np
    #读取原始载体图像
    lena=cv2.imread("lena.bmp",0)
    #读取水印图像
    watermark=cv2.imread("watermark.bmp",0)
    #将水印内的255处理为1,以方便嵌入
    #后续章节会介绍使用threshold处理。
    w=watermark[:,:]>0
    watermark[w]=1
    #读取原始载体图像的shape值
    r,c=lena.shape
    #============嵌入过程============
    #生成内部值都是254的数组
    t254=np.ones((r,c),dtype=np.uint8)*254
    #获取lena图像的高7位
    lenaH7=cv2.bitwise_and(lena,t254)
    #将watermark嵌入到lenaH7内
    e=cv2.bitwise_or(lenaH7,watermark)
    #============提取过程============
    #生成内部值都是1的数组
    t1=np.ones((r,c),dtype=np.uint8)
    #从载体图像内,提取水印图像
    wm=cv2.bitwise_and(e,t1)
    print(wm)
    #将水印内的1处理为255以方便显示
    #后续章节会介绍threshold实现。
    w=wm[:,:]>0
    wm[w]=255
    #============显示============
    cv2.imshow("lena",lena)
    cv2.imshow("watermark",watermark*255)   #当前watermark内最大值为1
    cv2.imshow("e",e)
    cv2.imshow("wm",wm)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    总结

    从图中可以发现,通过肉眼无法观察出含水印载体图像和原始图像的不同,水印的隐蔽性较高。但是,由于该方法过于简单,其安全性并不高,在实际处理中会通过更复杂的方法实现水印的嵌入。本文主要是为了给读者提供一个方法和思路,激发读者对OpenCV的学习热情。

    写在最后

    我也只是一个刚刚接触OpenCV的小白,今后遇到有意思的案例还会分享出来给大家,希望大家一起来交流经验互相学习!

    展开全文
  • import cv2 import numpy as np # 加载原始图片 oriImg = cv2.imread("shanghai.jpg", 0) r ,c = oriImg.shape cv2.namedWindow("origin",cv2.WINDOW_NORMAL) # 设置...# 加载水印图片 watermark = cv2.imread("wat.
    import cv2
    import numpy as np
    
    # 加载原始图片
    oriImg = cv2.imread("shanghai.jpg", 0)
    r ,c = oriImg.shape
    cv2.namedWindow("origin",cv2.WINDOW_NORMAL)  # 设置窗口尺寸
    cv2.imshow("origin", oriImg)
    cv2.imwrite('OriginImg.png',oriImg)
    
    # 加载水印图片
    watermark = cv2.imread("watermark.jpg", 0)
    r1 ,c1 = watermark.shape
    watermark = cv2.resize(watermark,(r1*6,c1*4))
    w1 = watermark[:,:]>200
    watermark[w1] = 0
    w2 = watermark[:,:]>200
    watermark[w2] = 1
    watermarkImg = np.zeros((r,c), dtype=np.uint8)
    r1 ,c1 = watermark.shape
    watermarkImg[600:600+r1,2000:2000+c1] = watermark
    cv2.namedWindow("watermark",cv2.WINDOW_NORMAL)
    cv2.imshow("watermark", watermarkImg)
    cv2.imwrite('WatermarkImg.png',watermarkImg)
    
    # 水印嵌入
    t254 = np.ones((r,c), dtype=np.uint8)*254 
    imgH7 = cv2.bitwise_and(oriImg, t254)
    resultImg = cv2.bitwise_or(imgH7, watermarkImg)
    cv2.namedWindow("result",cv2.WINDOW_NORMAL)
    cv2.imshow("result",resultImg)
    cv2.imwrite('ResultImg.png',resultImg)
    
    # 水印解码
    t1 = np.ones((r,c), dtype=np.uint8)
    delImg = cv2.bitwise_and(resultImg, t1)
    w3 = delImg[:,:]>0
    delImg[w3] = 255
    cv2.namedWindow("delete",cv2.WINDOW_NORMAL)
    cv2.imshow("delete",delImg)
    cv2.imwrite('DeleteImg.png',delImg)
    
    cv2.waitKey()
    cv2.destroyAllWindows()
    

     

     

     

    展开全文
  • 水印,你在很多公司图片都会看到,里面都会加入图片都会有显式水印,或者半隐形水印。 平常加水印,只要将两张图片色值混合就没问题了 import cv2 import numpy as np import matplotlib import matplotlib.pyplot ...

    水印,你在很多公司图片都会看到,里面都会加入图片都会有显式水印,或者半隐形水印。
    平常加水印,只要将两张图片色值混合就没问题了

    import cv2
    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    img  = cv2.imread("lena.jpg")
    img= cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    wm = cv2.imread("cang_wang.png")
    wm = cv2.resize(wm,(364,40))
    # wm = 255-wm
    img1 = cv2.resize(img,(600,600))
    //圈定感兴趣区域
    imgROI = img1[600-wm.shape[0]:600,600-wm.shape[1]:600]
    //图片透明度混合
    cv2.addWeighted(imgROI,0.5,wm,0.5,0,imgROI)
    plt.figure(figsize=(11,11))
    plt.imshow(img1)
    

    在这里插入图片描述
    这里引用到Opencv 图像叠加 添加水印

    数字水印是怎样的?
    1、预处理隐藏信息
    首先将需要加密的图像进行转换为二值图像,其中只包含两个灰度级0和1。其中0对应黑色,1对应白色。在opencv中其实没有二值图像,我们可以将二值图像理解为特殊的灰度图像。由于需要将隐藏信息嵌入图片的第0位(每个像素点分出一个bit位来存储信息)所以被隐藏信息图像的最高灰度级必须为1,最低为0。

    对图像进行二值化可以利用以下方法:

    s_black = s[:,:]<128 # s为需要被隐藏的图片 s_black记录灰度值小于128的像素的位置
    s[s_black] = 0 # 将灰度值小于128的灰度值置为0
    s_white = s[:]>=128 # s_white记录灰度值大于128的像素的位置
    s[s_white] = 1 # 将灰度值大于128的灰度值置为1
    这样就得到被标记为0和1的矩阵

    彩色图片色值0~255,我们可以借用RGB其中一个色值,然后转为二进制值,最后一位用来记录签名值。因为最后一位色值其实变化很小,用来记录二值化干扰非常小。

    # 因为没有现成的二值图像,在此的s图像是一个包含黑色和白色的彩色图像,因此在这里需要阈值化处理
    #这里水印图设置成原图大小,不然不能使用与或运算,如果有人知道抽取roi区域做与或运算的方法也可以告诉我
    wm_2 = cv2.resize(wm,(img.shape[1],img.shape[0]))
    plt.imshow(wm_2)
    s_black = wm_2[:,:]<128
    wm_2[s_black] = 1
    s_white = wm_2[:]>=128
    wm_2[s_white] = 0
    
    # r, c = img.shape
    r = img.shape[0]
    c = img.shape[1]
     
    # 构造提取原始图像高7位矩阵
    t255 = np.ones((r, c, 3), dtype=np.uint8)*254
     
    # # 获取原始图像的高七位
    demo_h7 = np.bitwise_and(img, t255)
    # plt.imshow(demo_h7)
     
    # # 嵌入水印
    demo_s_in = np.bitwise_or(demo_h7, wm_2)
    # plt.imshow(cv2.hconcat([demo_h7,demo_s_in]))
     
    # 生成提取矩阵
    t1 = np.ones((r, c, 3), dtype=np.uint8)
    s_out = np.bitwise_and(demo_s_in, t1)
    s_out_white = s_out[:]<1
    s_out[s_out_white] = 255
    # cv2.imshow("s_out", s_out)
    plt.figure(figsize=(11,11))
    plt.imshow(cv2.hconcat([demo_h7,demo_s_in,s_out]))
    

    在这里插入图片描述
    在这里插入图片描述
    可以看出加了水印的图,其实和原图没有太大的差别。
    因为我本来水印图色值还是有拉伸的,直接转化为0,1两个数字后,再和原图或值合并。
    所以还原回来看水印的还原还是有区域无法正常显示。

    数字水印的方式,其实抗干扰性非常之差,稍微进行

    这里应用OpenCv图像处理——数字水印

    频域水印
    所谓频域水印,首先需要了解傅里叶变换

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('lena.jpg',0) #直接读为灰度图像
    img = cv2.resize(img,(300,300))
    
    wm = cv2.imread("cang_wang.png", 0)
    wm = cv2.resize(wm,(200,50))
    wm = 255-wm
    
    #快速傅里叶变换算法得到频率分布
    f = np.fft.fft2(img)
    #默认结果中心点位置在左上角,转移到中间
    fshift = np.fft.fftshift(f)
    #取绝对值:将复数变化成实数
    #取对数的目的为了将数据变化到0-255
    #fshift是复数,求绝对值结果才是振幅
    s1 = np.log(np.abs(fshift))
    
    #求相位,相位和振幅是频域两个很重要的结果
    #振幅只是记录图片的明暗,而相位才是记录图像的形状
    s1_angle = np.angle(fshift)
    
    #将水印放入频域
    fshift2 = fshift.copy()
    fshift2[0:50, 0:200] += wm *50.0
    fshift2[-50:, -200:] += cv2.flip(wm, -1) *50.0
    
    s2 = np.log(np.abs(fshift2))
    
    # 逆变换
    f1shift2 = np.fft.ifftshift(fshift2)
    img_back2 = np.fft.ifft2(f1shift2)
    #出来的复数,无法显示,转成实数
    img_back2 = np.abs(img_back2)
    
    f1shift = np.fft.ifftshift(fshift)
    img_back = np.fft.ifft2(f1shift)
    #出来的是复数,无法显示
    img_back = np.abs(img_back)
    plt.figure()
    plt.imshow(img,'gray')
    plt.figure()
    plt.imshow(wm, 'gray')
    plt.figure()
    plt.imshow(s1,'gray')
    plt.figure()
    plt.imshow(s2,'gray')
    plt.figure()
    plt.imshow(img_back,'gray')
    
    plt.figure()
    plt.imshow(img_back2,'gray')
    

    原图
    在这里插入图片描述
    水印图
    在这里插入图片描述
    频域图
    在这里插入图片描述
    加水印后频域图
    在这里插入图片描述
    频域逆转换后图
    在这里插入图片描述
    频域加水印后逆转换后图
    在这里插入图片描述
    关于opencv使用傅里叶变换,可以参照一下这个文章OpenCV学习笔记-傅里叶变换
    关于频域水印再受到变换后可能出现的问题,可以参照这篇文章有意思的数字盲水印的简单的实现
    基本旋转平移、光暗调整等操作,不会对水印有太大影响,但是通过模糊算法后,水印会被刷除,但是锐化算法不会有太大影响。

    展开全文
  • OpenCv图像处理——数字水印

    千次阅读 2019-12-05 23:20:26
    前言 在一幅数字图像中最低有效位...数字水印的信息类型可以有很多种比如,文本、视频、音频二值图像等等。为了研究方便本文讨论数字水印为二值图像的情况。 实现过程 1、预处理隐藏信息 首先将需要加密的图像进...

    前言

    在一幅数字图像中最低有效位是指构成一个像素点的灰度值的二进制数的第0位,由于第0位的数值在图像的显示上面往往作用非常小,所含能量非常小,因此我们可以利用该性质,在数字图像的最低位加入需要隐藏的信息,该信息称之为数字水印。数字水印的信息类型可以有很多种比如,文本、视频、音频二值图像等等。为了研究方便本文讨论数字水印为二值图像的情况。


    实现过程

    1、预处理隐藏信息

    首先将需要加密的图像进行转换为二值图像,其中只包含两个灰度级0和1。其中0对应黑色,1对应白色。在opencv中其实没有二值图像,我们可以将二值图像理解为特殊的灰度图像。由于需要将隐藏信息嵌入图片的第0位(每个像素点分出一个bit位来存储信息)所以被隐藏信息图像的最高灰度级必须为1,最低为0。

    对图像进行二值化可以利用以下方法:

    s_black = s[:,:]<128    # s为需要被隐藏的图片  s_black记录灰度值小于128的像素的位置
    s[s_black] = 0          # 将灰度值小于128的灰度值置为0
    s_white = s[:]>=128     # s_white记录灰度值大于128的像素的位置
    s[s_white] = 1          # 将灰度值大于128的灰度值置为1
    

    2、提取载体图像高7位

    1. 构造提取高7位矩阵     提取高7位矩阵 为行列和载体图像行列相等的矩阵,矩阵中的每个值都为254
    2. 提取高7位                    将提取矩阵和载体图像按位与运算

    例如:

    179211
    153119

                                                                                                   原图像A

    1011  00111101  0011
    1001  10010111  0111

                                                                                           原图像的二进制表示AB

    254254
    254254

                                                                                              提取高7位矩阵T

    1111  11101111  1110
    1111  11101111  1110

                                                                                     提取高7位矩阵二进制表示TB

    将AB和TB按位与运算得到A矩阵的高7位AH7B如下:

    1011  00101101  0010
    1001  10000111  0110

    3、嵌入水印

    将表示隐藏图像的二进制图像与载体矩阵按位或运算,得到带有隐藏信息的图像。

    假设隐藏图像XB如下:

    0000 00010000 0000
    0000 00000000 0001

                                                                                            隐藏图像 XB

    XB与AH7B按位或运算得到带有隐藏信息的图像YB

    1011  00111101  0010
    1001  10000111  0111

                                                                                              带有隐藏信息的图像YB

    4、提取水印

    (1)构造提取矩阵GB

    提取矩阵是一个所有灰度值均为1的矩阵,行列与载体矩阵的行列一样。

    0000 00010000 0001
    0000 00010000 0001

    (2)提取矩阵GB与带有隐藏信息的图像YB按位与运算得到水印矩阵ZB

    0000 00010000 0000
    0000 00000000 0001

                                                                                               水印矩阵ZB

    可以看出水印矩阵ZB和带隐藏信息的矩阵XB完全一致。

    (3)接下来就是将ZB矩阵中灰度值大于0的像素点的灰度值该为255。该过程与第一步预处理隐藏信息过程相反,详情见下面代码。

    代码实现

                            

                                                        原始图像                                                                           水印图片

    import cv2 
    import numpy as np
    
    demo = cv2.imread("demo.jpg", 0)
    cv2.imshow("demo", demo)
    
    s = cv2.imread("s.jpg", 0)   # 因为没有现成的二值图像,在此的s图像是一个包含黑色和白色的彩色图像,因此在这里需要阈值化处理
    cv2.imshow("s", s)
    s_black = s[:,:]<128
    s[s_black] = 0
    s_white = s[:]>=128
    s[s_white] = 1
    
    r, c = demo.shape
    
    # 构造提取原始图像高7位矩阵
    t255 = np.ones((r, c), dtype=np.uint8)*254
    
    # 获取原始图像的高七位
    demo_h7 = np.bitwise_and(demo, t255)
    cv2.imshow("demo_h7", demo_h7)
    
    # 嵌入水印
    demo_s_in = np.bitwise_or(demo_h7, s)
    cv2.imshow("demo_s_in", demo_s_in)
    
    # 生成提取矩阵
    t1 = np.ones((r, c), dtype=np.uint8)
    s_out = np.bitwise_and(demo_s_in, t1)
    s_out_white = s_out[:]>0
    s_out[s_out_white] = 255
    cv2.imshow("s_out", s_out)
    
    cv2.waitKey(-1)
    cv2.destroyAllWindows()

                                 

                                                    高7位图像                                                          带有数字水印的图像

                      

                                           提取出来的数字水印

    展开全文
  • 基于C++和opencv数字图像水印系统源代码,可编译运行和学习,含有图像数据。
  • 利用opencv for python在lena图中隐藏了数字水印 非常之奇妙有趣,主要是利用了位运算 from cv2 import cv2 import numpy as np lena = cv2.imread('black.bmp') watermark = cv2.imread('watermask.bmp') #图片原本...
  • 给图片嵌入水印、提取水印
  • C++:图片数字水印-基于OpenCV+LSB

    千次阅读 2019-08-26 01:20:43
    失真后的图片水印也不会像之前那么清楚,这也是这个方法测试下来的一大缺点! 二、源码C: /************************************************************************* > File Name: 001_waterMarkLSB.cpp ...
  • opencv数字图像去除噪声

    热门讨论 2011-07-10 20:45:29
    opencv数字图像 去除噪声,的源代码程序。学习一下。 opencv数字图像 去除噪声,的源代码程序。学习一下。opencv数字图像 去除噪声,的源代码程序。学习一下。
  • OPENCV实现隐藏水印

    千次阅读 2018-09-18 17:42:04
    频域添加数字水印的方法,是指通过某种变换手段(傅里叶变换,离散余弦变换,小波变换等)将图像变换到频域(小波域),在频域对图像添加水印,再通过逆变换,将图像转换为空间域。 代码 原理很简单,实现也很简洁...
  • 在前面博文讲解位平面分解的时候,我们就提到过可以通过位平面分解的方式给图像添加水印。而数值水印是图片版权用到最多的加密方式。 通过在最低有效位的位平面分解图中隐藏二值图像信息,具有极高的隐蔽性。所以,...
  • 嵌入时先将数字水印处理成二值(0 1)图像, 然后利用位操作插入原图的最后一个位平面,这样在观感上不会对原图造成任何影响。 提取时相反操作即可。 from operator import mod import cv2 import numpy as np...
  • Python版本是Python3.7.3,OpenCV版本OpenCV.3.4.1,开发环境为PyCharm 最低有效位(Least Significant Bit, LSB)指的是一个二进制数中的第0位(即最低位)。最低有效位信息隐藏指的是,将一个需要隐藏的二值图像...
  • opencv入门:图像与数值的计算,位平面分解,图像加密和解密,数字水印,脸部打码及解码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 752
精华内容 300
关键字:

opencv数字水印