图像中看不见的水印

时间:2008-09-04 16:15:43

标签: python image watermark

为了版权目的,如何在图像中插入隐形水印?我正在寻找一个python库。

您使用什么算法?性能和效率如何?

11 个答案:

答案 0 :(得分:7)

你可能想看看隐写术;这是隐藏数据内部的数据。如果转换为有损格式甚至裁剪出部分图像,有些表格不会丢失。

答案 1 :(得分:4)

我使用以下代码。它需要PIL:

def reduceOpacity(im, opacity):
    """Returns an image with reduced opacity."""
    assert opacity >= 0 and opacity <= 1
    if im.mode != 'RGBA':
        im = im.convert('RGBA')
    else:
        im = im.copy()
    alpha = im.split()[3]
    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
    im.putalpha(alpha)
    return im

def watermark(im, mark, position, opacity=1):
    """Adds a watermark to an image."""
    if opacity < 1:
        mark = reduceOpacity(mark, opacity)
    if im.mode != 'RGBA':
        im = im.convert('RGBA')
    # create a transparent layer the size of the image and draw the
    # watermark in that layer.
    layer = Image.new('RGBA', im.size, (0,0,0,0))
    if position == 'tile':
        for y in range(0, im.size[1], mark.size[1]):
            for x in range(0, im.size[0], mark.size[0]):
                layer.paste(mark, (x, y))
    elif position == 'scale':
        # scale, but preserve the aspect ratio
        ratio = min(float(im.size[0]) / mark.size[0], float(im.size[1]) / mark.size[1])
        w = int(mark.size[0] * ratio)
        h = int(mark.size[1] * ratio)
        mark = mark.resize((w, h))
        layer.paste(mark, ((im.size[0] - w) / 2, (im.size[1] - h) / 2))
    else:
        layer.paste(mark, position)
    # composite the watermark with the layer
    return Image.composite(layer, im, layer)

img = Image.open('/path/to/image/to/be/watermarked.jpg')

mark1 = Image.open('/path/to/watermark1.png')
mark2 = Image.open('/path/to/watermark2.png')

img = watermark(img, mark1, (img.size[0]-mark1.size[0]-5, img.size[1]-mark1.size[1]-5), 0.5)
img = watermark(img, mark2, 'scale', 0.01)

水印太模糊了。只有纯色图像才会显示出来。我可以使用它来创建一个不显示水印的图像,但如果我使用原始图像进行逐位减法,我可以证明我的水印就在那里。

如果您想查看其工作原理,请转到TylerGriffinPhotography.com。网站上的每个图像都被加水印两次:一次是右下角的水印,50%不透明度(距离边缘5px),一次覆盖整个图像,1%不透明度(使用“比例”,将水印缩放到整个图像)。你能弄清楚第二个低不透明度的水印形状是什么吗?

答案 2 :(得分:2)

我正在寻找“牢不可破的”水印,因此exif或图像元数据中存储的数据都已用完。

我在网上等待回复时发现了一些有趣的东西: http://www.cosy.sbg.ac.at/~pmeerw/Watermarking/

有一个硕士论文对于算法及其特性(他们做了什么,以及他们是多么牢不可破)都相当详尽。我没有时间深入阅读,但这些东西看起来很严肃。有些算法以某种方式支持JPEG压缩,裁剪,伽马校正或缩小比例。它是C,但我可以将它移植到Python或使用Python中的C库。

然而,从2001年开始,我猜这个领域已有7年了很长时间:(有没有人有类似的和最近的东西?

答案 3 :(得分:2)

如果你在谈论隐写术,这里有一个旧的不太花哨的模块我曾经为朋友做过一次(Python 2.x代码):

代码

from __future__ import division

import math, os, array, random
import itertools as it
import Image as I
import sys

def encode(txtfn, imgfn):
    with open(txtfn, "rb") as ifp:
        txtdata= ifp.read()
    txtdata= txtdata.encode('zip')

    img= I.open(imgfn).convert("RGB")
    pixelcount= img.size[0]*img.size[1]
##  sys.stderr.write("image %dx%d\n" % img.size)

    factor= len(txtdata) / pixelcount
    width= int(math.ceil(img.size[0]*factor**.5))
    height= int(math.ceil(img.size[1]*factor**.5))

    pixelcount= width * height
    if pixelcount < len(txtdata): # just a sanity check
        sys.stderr.write("phase 2, %d bytes in %d pixels?\n" % (len(txtdata), pixelcount))
        sys.exit(1)
##  sys.stderr.write("%d bytes in %d pixels (%dx%d)\n" % (len(txtdata), pixelcount, width, height))
    img= img.resize( (width, height), I.ANTIALIAS)

    txtarr= array.array('B')
    txtarr.fromstring(txtdata)
    txtarr.extend(random.randrange(256) for x in xrange(len(txtdata) - pixelcount))

    newimg= img.copy()
    newimg.putdata([
        (
            r & 0xf8 |(c & 0xe0)>>5,
            g & 0xfc |(c & 0x18)>>3,
            b & 0xf8 |(c & 0x07),
        )
        for (r, g, b), c in it.izip(img.getdata(), txtarr)])
    newimg.save(os.path.splitext(imgfn)[0]+'.png', optimize=1, compression=9)

def decode(imgfn, txtfn):
    img= I.open(imgfn)
    with open(txtfn, 'wb') as ofp:
        arrdata= array.array('B',
            ((r & 0x7) << 5 | (g & 0x3) << 3 | (b & 0x7)
            for r, g, b in img.getdata())).tostring()
        findata= arrdata.decode('zip')
        ofp.write(findata)

if __name__ == "__main__":
    if sys.argv[1] == 'e':
        encode(sys.argv[2], sys.argv[3])
    elif sys.argv[1] == 'd':
        decode(sys.argv[2], sys.argv[3])

算法

它使用以下方法存储每个图像像素的一个字节数据:蓝色波段的3个最低有效位,绿色波段的2个LSB和红色波段的3个LSB。

编码功能:输入文本文件由zlib压缩,输入图像调整大小(保持比例),以确保至少有与压缩字节一样多的像素。与输入图像同名的 PNG 图像(因此,如果保留代码,请不要使用“.png”文件名作为输入:)保存包含隐写数据。< / p>

解码功能:先前存储的zlib压缩数据从输入图像中提取,并在提供的文件名下保存未压缩。

我验证了旧代码仍在运行,所以这是一个包含隐写数据的示例图片:

contains steganographic data

您会注意到添加的噪音几乎不可见。

答案 4 :(得分:1)

Exif怎么样?它可能不像你想的那么安全,但是大多数用户甚至不知道它存在,如果你能够轻松阅读水印信息,那些关心的人仍然可以做到这一点。

答案 5 :(得分:1)

我认为没有一个库开箱即用。如果你想实现自己的,我肯定会选择Python Imaging Library(PIL)。

这是a Python Cookbook recipe,它使用PIL为图像添加可见水印。如果它足以满足您的需求,您可以使用它来添加具有足够透明度的水印,只有在您知道要查找的内容时才能看到它。

答案 6 :(得分:1)

嗯,看不见的水印并不那么容易。检查digimarc,他们赚了多少钱。没有免费的C / Python代码,一个孤独的天才写了一个免费使用它。我已经实现了自己的算法,工具的名称是SignMyImage。谷歌如果有兴趣... F&gt;

答案 7 :(得分:1)

watermarkingworld.org

上有一个较新的(2005)数字水印常见问题解答

答案 8 :(得分:0)

我打算发一个类似于Ugh的答案。我建议将一个描述图像源的小型TXT文件(可能是一个小的版权声明,如果适用的话)以难以检测和破坏的方式放入图像中。

答案 9 :(得分:0)

我不确定它是不可破坏的重要性,但一个简单的解决方案可能只是将文本文件附加到图像的末尾。像“这个图像属于......”之类的东西。

如果您在查看器/浏览器中打开图像,它看起来像普通的jpeg,但如果您在文本编辑器中打开它,则最后一行是可读的。

同样的方法允许您将实际文件包含到图像中。 (hide a file inside of an image)我发现它有点受欢迎,但7-zip文件似乎有效。你可以在图像中隐藏各种各样的copywrite好东西。

同样,它不会因任何想象力而牢不可破,但它肉眼完全看不见。

答案 10 :(得分:0)

某些图片格式也有标题,您也可以存储任意信息 例如,PNG specification有一个块,您可以在其中存储文本数据。这与上面的答案类似,但没有将随机数据添加到图像数据本身。