python image watermark

python - marcas de agua invisibles en imágenes



image watermark (11)

¿Qué hay de Exif? Probablemente no sea tan seguro como lo que estás pensando, pero la mayoría de los usuarios ni siquiera saben que existe y si haces que sea tan fácil leer la información de la marca de agua, los que se preocupan aún podrán hacerlo de todos modos.

¿Cómo se insertan marcas de agua invisibles en las imágenes con fines de copyright? Estoy buscando una biblioteca de Python.

¿Qué algoritmo usas? ¿Qué hay de rendimiento y eficiencia?


Algunos formatos de imagen tienen encabezados donde también puedes almacenar información arbitraria.
Por ejemplo, la especificación PNG tiene un fragmento donde puede almacenar datos de texto. Esto es similar a las respuestas anteriores, pero sin agregar datos aleatorios a los datos de la imagen en sí.


Es posible que desee examinar esteganografía; eso es ocultar datos dentro de las imágenes. Hay formularios que no se perderán si los convierte a un formato de pérdida o incluso recorta partes de la imagen.


Estoy buscando marcas de agua "irrompibles", por lo que los datos almacenados en exif o metadatos de imagen están fuera.

He encontrado algunas cosas interesantes en la web mientras espero respuestas aquí: http://www.cosy.sbg.ac.at/~pmeerw/Watermarking/

Hay una tesis maestra que es bastante exhaustiva sobre los algoritmos y sus características (lo que hacen y lo irrompibles que son). No tengo tiempo para leerlo en profundidad, pero esto parece serio. Hay algoritmos que admiten compresión JPEG, recorte, corrección gamma o reducción de escala de alguna manera. Es C, pero puedo portarlo a Python o usar bibliotecas C desde Python.

Sin embargo, es de 2001 y creo que 7 años son mucho tiempo en este campo :( ¿Alguien tiene algo similar y más reciente?


Iba a publicar una respuesta similar a Ugh. Sugeriría poner un pequeño archivo TXT que describa la fuente de la imagen (y tal vez una pequeña declaración de derechos de autor, si corresponde) en la imagen de una manera que sea difícil de detectar y romper.


No creo que haya una biblioteca que haga esto de la caja. Si desea implementar el suyo, definitivamente iría con la Biblioteca de imágenes de Python (PIL).

Esta es una receta de Python Cookbook que usa PIL para agregar una marca de agua visible a una imagen. Si es suficiente para sus necesidades, puede usar esto para agregar una marca de agua con suficiente transparencia para que solo sea visible si sabe lo que está buscando.


No estoy seguro de lo importante que es ser irrompible, pero una solución simple podría ser simplemente agregar un archivo de texto al final de la imagen. Algo así como "Esta imagen pertenece a ...".

Si abre la imagen en un visor / navegador, se ve como un jpeg normal, pero si lo abre en un editor de texto, la última línea sería legible.

El mismo método le permite incluir un archivo real en una imagen. ( esconde un archivo dentro de una imagen ) He encontrado que es un poco acertado, pero los archivos 7-zip parecen funcionar. Podrías esconder todo tipo de objetos de copywrite dentro de la imagen.

Una vez más, no es irrompible en ningún momento de la imaginación, pero es completamente invisible a simple vista.


Yo uso el siguiente código. Requiere 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)

La marca de agua es demasiado débil para ver. Solo una imagen de color sólido realmente lo mostraría. Puedo usarlo para crear una imagen que no muestre una marca de agua, pero si hago una resta de bit a bit usando la imagen original, puedo demostrar que mi marca de agua está allí.

Si desea ver cómo funciona, vaya a TylerGriffinPhotography.com . Cada imagen en el sitio tiene marca de agua dos veces: una con la marca de agua en la esquina inferior derecha con 50% de opacidad (5px desde el borde) y una vez con toda la imagen al 1% de opacidad (usando "escala", que escala la marca de agua a toda la imagen). ¿Puedes averiguar cuál es la segunda forma de marca de agua de baja opacidad?


Bueno, las marcas de agua invisibles no son tan fáciles. Compruebe digimarc, qué dinero ganaron en él. No hay un código C / Python gratuito que haya escrito un genio solitario y lo dejes para el uso gratuito. Implementé mi propio algoritmo y el nombre de la herramienta es SignMyImage. Google si está interesado ... F>



Si estás hablando de esteganografía , aquí hay un módulo antiguo que no era demasiado elegante y lo hice para un amigo una vez (código de Python 2.x):

el código

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])

el algoritmo

Almacena un byte de datos por píxel de imagen usando: los 3 bits menos significativos de la banda azul, los 2 LSB del verde y los 3 LSB del rojo.

Función de codificación: Zlib comprime un archivo de texto de entrada y la imagen de entrada se redimensiona (manteniendo las proporciones) para garantizar que haya al menos tantos píxeles como bytes comprimidos. Una imagen PNG con el mismo nombre que la imagen de entrada (así que no use un nombre de archivo ".png" como entrada si deja el código tal como está) se guarda con los datos esteganográficos.

función de decodificación: los datos zlib comprimidos previamente almacenados se extraen de la imagen de entrada y se guardan sin comprimir con el nombre de archivo proporcionado.

Verifiqué que el código anterior aún se ejecuta, así que aquí hay una imagen de ejemplo que contiene datos esteganográficos:

Notarás que el ruido agregado es apenas visible.