出于版权目的,您如何在图像中插入不可见的水印?我正在寻找一个python库。
你用什么算法?性能和效率如何?
You might want to look into Steganography; that is hiding data inside of images. There are forms that won't get lost if you convert to a lossier format or even crop parts of the image out.
我正在寻找“牢不可破”的水印,因此存储在 exif 或图像元数据中的数据已经失效。
我在这里等待回复时在网上发现了一些有趣的东西:http: //www.cosy.sbg.ac.at/~pmeerw/Watermarking/
有一篇关于算法及其特征(它们做什么以及它们有多牢不可破)的硕士论文相当详尽。我没有时间深入阅读它,但这些东西看起来很严肃。有些算法以某种方式支持 JPEG 压缩、裁剪、伽马校正或缩小比例。它是 C,但我可以将它移植到 Python 或使用 Python 中的 C 库。
然而,它是从 2001 年开始的,我想 7 年在这个领域已经很长了 :( 有没有人有一些类似的和更新的东西?
我使用以下代码。它需要 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% 不透明度(使用“缩放”,将水印缩放到整个图像)。你能弄清楚第二个低不透明度水印形状是什么吗?
如果您在谈论steganography,这是我曾经为朋友做过的一个不太花哨的旧模块(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”文件名作为输入:)包含隐写数据。
decode 函数:从输入图像中提取先前存储的 zlib 压缩数据,并以提供的文件名未压缩保存。
我验证了旧代码仍在运行,所以这是一个包含隐写数据的示例图像:
您会注意到添加的噪声几乎不可见。
好吧,隐形水印并不是那么容易。检查 digimarc,他们从中赚了多少钱。没有一个孤独的天才编写的免费 C/Python 代码可以免费使用。我已经实现了自己的算法,工具的名称是 SignMyImage。如果有兴趣,请谷歌... F>
Exif呢?它可能不像您想象的那么安全,但大多数用户甚至不知道它的存在,如果您可以轻松阅读水印信息,那么关心的人仍然可以做到这一点。
我认为没有一个图书馆可以开箱即用。如果你想实现自己的,我肯定会使用Python Imaging Library (PIL)。
这是一个 Python Cookbook 食谱,它使用 PIL 向图像添加可见水印。如果它足以满足您的需求,您可以使用它来添加具有足够透明度的水印,只有在您知道要查找的内容时才可见。
watermarkingworld.org 上有更新的 (2005) 数字水印常见问题解答
I was going to post an answer similar to Ugh. I would suggest putting a small TXT file describing the image source (and perhaps a small copyright statement, if one applies) into the image in a manner that is difficult to detect and break.
I'm not sure how important it is to be unbreakable, but a simple solution might just be to append a text file to the end of the image. Something like "This image belongs to ...".
If you open the image in a viewer/browser, it looks like a normal jpeg, but if you open it in a text editor, the last line would be readable.
The same method allows you include an actual file into an image. (hide a file inside of an image) I've found that it's a bit hit-or-miss, but 7-zip files seem to work. You could hide all sorts of copywrite goodies inside the image.
Again, it's not unbreakable by any stretch of the imagination, but it's completely invisible to the naked eye.
某些图像格式具有标题,您也可以在其中存储任意信息。
例如,PNG 规范有一个可以存储文本数据的块。这类似于上面的答案,但没有向图像数据本身添加随机数据。