Python实现图像空域随机水印加入与提取

本文要点在于Python扩展库pillow中Image类的运用。图像空域随机水印的主要思路在于:在原始图像中随机选取一些位置替换为水印图片中的非背景像素,同时生成日志文件记录替换的位置和水印中像素位置的对应关系,然后可以根据加入水印的图片和日志文件来提取和验证水印。

from os import remove

from os.path import isfile 

from random import sample, choice

from PIL import Image

def mergeWaterMark(originPic, watermarkPic, logTxt):

    #原始图片和水印文件必须为图片格式

    if (not originPic.endswith(('.jpg', '.bmp', '.png'))) or (not watermarkPic.endswith(('.jpg', '.bmp', '.png'))):

        return 'Error format.'

    

    #打开原图和水印图片,并获取大小

    imOrigin = Image.open(originPic)

    originWidth, originHeight = imOrigin.size

    imWaterMark = Image.open(watermarkPic)

    watermarkWidth, watermarkHeight = imWaterMark.size

    #随机生成水印位置

    allPositions = [(w,h) for w in range(originWidth) for h in range(originHeight)]

    positions = sample(allPositions, watermarkWidth*watermarkHeight)

    fpLog = open(logTxt, 'w')

    #写入水印文件大小

    fpLog.write(str((watermarkWidth,watermarkHeight))+'\n')

    

    for w in range(watermarkWidth):

        for h in range(watermarkHeight):

            c = imWaterMark.getpixel((w,h))

            c = c[:3]

            #只写入不是白色的像素

            if c != (255,255,255):

                p = choice(positions)

                #写入像素值

                imOrigin.putpixel(p, c)

                #避免重复修改同一个像素

                positions.remove(p)

                #生成日志文件,用来提取水印

                fpLog.write(str(p+(w,h))+'\n')

    fpLog.close()

    #生成加入水印的新图片

    imOrigin.save(originPic[:-4]+'_new'+originPic[-4:])

def restoreWaterMark(mergedPic, logTxt, watermarkPic):

    #删除原来提取过的水印文件

    if isfile(watermarkPic):

        remove(watermarkPic)

    imMerged = Image.open(mergedPic)

    with open(logTxt) as fp:

        for line in fp:

            #读取每一行并还原为元组

            line = eval(line.strip())

            #第一行是水印图片尺寸,先创建水印文件

            if len(line)==2:

                imWaterMark = Image.new('RGB', line, (255,255,255))

            else:

                #提取水印像素并写入水印文件

                c = imMerged.getpixel((line[0],line[1]))

                c = c[:3]

                imWaterMark.putpixel((line[2],line[3]), c)

    #保存提取的水印

    imWaterMark.save(watermarkPic)

#测试

mergeWaterMark('origin.bmp', 'watermark.png', 'logg.txt')

restoreWaterMark('origin_new.bmp', 'logg.txt', 'restoredWaterMark.png')

测试用的原始图片:

测试用的水印图片:


加入水印以后的图片:


提取出来的水印:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dongfuguo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值