python 图像中的不可见水印
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
invisible watermarks in images
提问by Grégtheitroade Cachet
How do you insert invisible watermarks in images for copyright purposes? I'm looking for a python library.
出于版权目的,您如何在图像中插入隐形水印?我正在寻找一个 python 库。
What algorithm do you use? What about performance and efficiency?
你用什么算法?性能和效率如何?
回答by Grégtheitroade Cachet
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.
你可能想研究隐写术;即在图像中隐藏数据。如果您转换为有损格式或什至裁剪掉图像的一部分,则有些表格不会丢失。
回答by tghw
I use the following code. It requires PIL:
我使用以下代码。它需要 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)
The watermark is too faint to see. Only a solid color image would really show it. I can use it to create an image that doesn't show a watermark, but if I do a bit-by-bit subtraction using the original image, I can demonstrate that my watermark is there.
水印太微弱看不清。只有纯色图像才能真正显示它。我可以用它来创建一个不显示水印的图像,但是如果我使用原始图像进行逐位减法,我可以证明我的水印在那里。
If you want to see how it works, go to TylerGriffinPhotography.com. Each image on the site is watermarked twice: once with the watermark in the lower right corner at 50% opacity (5px from the edge), and once over the whole image at 1% opacity (using "scale", which scales the watermark to the whole image). Can you figure out what the second, low opacity watermark shape is?
如果您想了解它是如何工作的,请访问TylerGriffinPhotography.com。网站上的每张图像都加了两次水印:一次在右下角的水印不透明度为 50%(距边缘 5px),一次在整个图像上的不透明度为 1%(使用“缩放”,将水印缩放到整个图像)。你能弄清楚第二个低不透明度水印形状是什么吗?
回答by Grégtheitroade Cachet
I'm looking for "unbreakable" watermarks, so data stored in exif or image metadata are out.
我正在寻找“牢不可破”的水印,因此存储在 exif 或图像元数据中的数据已被删除。
I have found some interesting stuff on the web while waiting for replies here: http://www.cosy.sbg.ac.at/~pmeerw/Watermarking/
我在这里等待回复时在网上发现了一些有趣的东西:http: //www.cosy.sbg.ac.at/~pmeerw/Watermarking/
There is a master thesis that's fairly exhaustive about algorithms and their caracteristics (what they do and how unbreakable they are). I haven't got any time to read it in depth, but this stuff looks serious. There are algorithms that support JPEG compression, cropping, gamma correction or down scaling in some way. It's C, but I can port it to Python or use C libraries from Python.
有一篇硕士论文相当详尽地介绍了算法及其特征(它们做了什么以及它们是多么牢不可破)。我没有时间深入阅读它,但这东西看起来很严重。有些算法以某种方式支持 JPEG 压缩、裁剪、伽马校正或缩小。它是 C,但我可以将它移植到 Python 或使用 Python 中的 C 库。
However, it's from 2001 and I guess 7 years are a long time in this field :( Does anybody have some similar and more recent stuff?
然而,它是从 2001 年开始的,我想 7 年在这个领域已经很长了 :( 有没有人有一些类似的和最近的东西?
回答by tzot
If you're talking about steganography, here's an old not too-fancy module I did for a friend once (Python 2.x code):
如果你在谈论隐写术,这里有一个我曾经为朋友做过的一个不太花哨的旧模块(Python 2.x 代码):
the code
代码
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])
the algorithm
算法
It stores a byte of data per image pixel using: the 3 least-significant bits of the blue band, the 2 LSB of the green one and the 3 LSB of the red one.
它使用以下方式为每个图像像素存储一个字节的数据:蓝色波段的 3 个最低有效位、绿色波段的 2 LSB 和红色波段的 3 LSB。
encode function: An input text file is compressed by zlib, and the input image is resized (keeping proportions) to ensure that there are at least as many pixels as compressed bytes. A PNGimage with the same name as the input image (so don't use a ".png" filename as input if you leave the code as-is :) is saved containing the steganographic data.
encode 函数:输入文本文件由 zlib 压缩,并调整输入图像的大小(保持比例)以确保至少有与压缩字节一样多的像素。一个PNG具有相同的名称作为输入图像的图像(所以不要,如果你离开代码按:)保存含有隐写数据使用“png格式”文件名作为输入。
decode function: The previously stored zlib-compressed data are extracted from the input image, and saved uncompressed under the provided filename.
解码功能:先前存储的 zlib 压缩数据从输入图像中提取,并以提供的文件名未压缩保存。
I verified the old code still runs, so here's an example image containing steganographic data:
我验证了旧代码仍然运行,所以这是一个包含隐写数据的示例图像:
You'll notice that the noise added is barely visible.
您会注意到添加的噪音几乎不可见。
回答by tzot
Well, invisible watermarking is not that easy. Check digimarc, what money did they earn on it. There is no free C/Python code that a lonely genius has written a leave it for free usage. I've implemented my own algorithm and the name of the tool is SignMyImage. Google it if interested ... F>
嗯,隐形水印并不是那么容易。检查digimarc,他们赚了多少钱。没有免费的 C/Python 代码是一个孤独的天才编写的,可以免费使用。我已经实现了自己的算法,该工具的名称是 SignMyImage。有兴趣的话谷歌一下... F>
回答by JeffH
There is a newer (2005) digital watermarking FAQ at watermarkingworld.org
有一个较新的(2005)数字水印的常见问题watermarkingworld.org
回答by Joel Coehoorn
What about Exif? It's probably not as secure as what you're thinking, but most users don't even know it exists and if you make it that easy to read the watermark information those who care will still be able to do it anyway.
Exif呢?它可能不像你想象的那么安全,但大多数用户甚至不知道它的存在,如果你让阅读水印信息变得如此容易,那些关心的人仍然可以这样做。
回答by dF.
I don't think there is a library that does this out of the box. If you want to implement your own, I would definitely go with the Python Imaging Library(PIL).
我不认为有一个开箱即用的图书馆。如果你想实现你自己的,我肯定会选择Python Imaging Library(PIL)。
This is a Python Cookbook recipethat uses PIL to add a visiblewatermark to an image. If it's enough for your needs, you could use this to add a watermark with enough transparency that it is only visible if you know what you are looking for.
这是一个 Python Cookbook 配方,它使用 PIL 为图像添加可见水印。如果这足以满足您的需求,您可以使用它来添加具有足够透明度的水印,只有在您知道要查找的内容时才可见。
回答by Thomas Owens
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.
我打算发布一个类似于呃的答案。我建议将一个描述图像来源的小 TXT 文件(可能还有一个小的版权声明,如果适用)以一种难以检测和破坏的方式放入图像中。
回答by Grant
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.
如果您在查看器/浏览器中打开图像,它看起来像普通的 jpeg,但如果您在文本编辑器中打开它,最后一行将是可读的。
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.
相同的方法允许您将实际文件包含到图像中。(在图像中隐藏一个文件)我发现它有点偶然,但 7-zip 文件似乎可以工作。您可以在图像中隐藏各种文案好东西。
Again, it's not unbreakable by any stretch of the imagination, but it's completely invisible to the naked eye.
再说一次,它不是通过任何想象力都牢不可破的,但它是肉眼完全看不见的。