当前位置: 首页 > 面试题库 >

比较原始图像和可能不需要原始图像的已编辑图像的另一种方法

廖琨
2023-03-14
问题内容

前一段时间,我做了一个python脚本来将数据存储在图像中,但是它有一个小问题,我只是想知道是否有人可以想到另一种方法。

一个非常基本的想法是它会腌制某些东西,然后在第一个版本中,它直接将ASCII数字写为像素(因为所有数字都在0到255之间)。这将导致图像看起来有点像电视噪音。

在写入实际图像时,它将检测到需要调整的每个像素的最小位数,因此它不会被人眼察觉,并且它将拆分数据并从每个像素中添加或减去一些位数,第一个像素存储其使用的方法。然后,我将URL作为文件存储在图像中,并可以使用第一个像素中给出的规则将URL中的原始图像与当前图像进行比较,从而将其反转。

一点python伪代码,以防我没有很好地解释:

original_image = (200, 200, 200, 100, 210, 255...)
stuff_to_store = "test"
#Convert anything into a list of bytes
data_numbers = [bin(ord(x)) for x in cPickle.dumps(stuff_to_store)]

#This is calculated by the code, but for now it's 2
bytes_per_pixel = 2
store_mode = 'subtract'

#Join the bytes and split them every 2nd character
new_bytes = "".join(data_bytes)
new_bytes_split = [new_bytes[i:i+bytes_per_pixel] for i in range(0, len(new_bytes), bytes_per_pixel)]

#Edit the pixels (by subtraction in this case)
pixel_data = []
for i in range(len(original_image)):
    pixel_data = original_image[i] - int(new_bytes_split[i])

但是,由于脚本的全部目的是通过修改像素来存储内容,因此将原始图像URL存储为文件感觉有点不明智。我以为将URL存储为前几个像素,但是只要图像不是灰色,它就会以明显的一行结尾。同样,这种方式效率极低,因为它需要两个图像才能正常工作,因此如果有人对如何避免这种想法有所了解,那就太好了。

如果有人感兴趣的话,这里是原始代码,我在学习编写文档之前就做了,所以很难弄清楚,现在只是问这个问题,因为我打算重写它,并且希望做得更好。


问题答案:

这是一种使用PIL进行图像处理的方法,可将数据嵌入到每个通道8位RGB图像文件中像素的每个颜色通道的最低有效位。

下面的代码说明了Python中的位流处理。这是相当有效的(只要这样的操作 可以 使用Python高效的),但它牺牲效率使用的可读性和简单性,必要时。:)

#! /usr/bin/env python

''' Steganography with PIL (really Pillow)

    Encodes / decodes bits of a binary data file into the LSB of each color 
    value of each pixel of a non-palette-mapped image.

    Written by PM 2Ring 2015.02.03
'''

import sys
import getopt
import struct
from PIL import Image


def readbits(bytes):
    ''' Generate single bits from bytearray '''
    r = range(7, -1, -1)
    for n in bytes:
        for m in r:
            yield (n>>m) & 1

def encode(image_bytes, mode, size, dname, oname):
    print 'Encoding...'
    with open(dname, 'rb') as dfile:
        payload = bytearray(dfile.read())

    #Prepend encoded data length to payload
    datalen = len(payload)
    print 'Data length:', datalen

    #datalen = bytearray.fromhex(u'%06x' % datalen)
    datalen = bytearray(struct.pack('>L', datalen)[1:])
    payload = datalen + payload

    databits = readbits(payload)
    for i, b in enumerate(databits):
        image_bytes[i] = (image_bytes[i] & 0xfe) | b

    img = Image.frombytes(mode, size, str(image_bytes))
    img.save(oname)


def bin8(i): 
    return bin(i)[2:].zfill(8)

bit_dict = dict((tuple(int(c) for c in bin8(i)), i) for i in xrange(256))

def decode_bytes(data):
    return [bit_dict[t] for t in zip(*[iter(c&1 for c in data)] * 8)]

def decode(image_bytes, dname):
    print 'Decoding...'
    t = decode_bytes(image_bytes[:24])
    datalen = (t[0] << 16) | (t[1] << 8) | t[2]
    print 'Data length:', datalen

    t = decode_bytes(image_bytes[24:24 + 8*datalen])

    with open(dname, 'wb') as dfile:
        dfile.write(str(bytearray(t)))


def process(iname, dname, oname):
    with Image.open(iname) as img:
        mode = img.mode
        if mode == 'P':
            raise ValueError, '%s is a palette-mapped image' % fname
        size = img.size
        image_bytes = bytearray(img.tobytes())
    #del img

    print 'Data capacity:', len(image_bytes) // 8 - 24

    if oname:
        encode(image_bytes, mode, size, dname, oname)
    elif dname:
        decode(image_bytes, dname)


def main():
    #input image filename
    iname = None
    #data filename
    dname = None
    #output image filename
    oname = None

    def usage(msg=None):
        s = msg + '\n\n' if msg else ''
        s += '''Embed data into or extract data from the low-order bits of an image file.

Usage:

%s [-h] -i input_image [-d data_file] [-o output_image]

To encode, you must specify all 3 file names.
To decode, just specify the input image and the data file names.
If only the the input image is given, its capacity will be printed,
i.e., the maximum size (in bytes) of data that it can hold.

Uses PIL (Pillow) to read and write the image data.
Do NOT use lossy image formats for output, eg JPEG, or the data WILL get scrambled.
The program will abort if the input image is palette-mapped, as such images
are not suitable.
'''
        print >>sys.stderr, s % sys.argv[0]
        raise SystemExit, msg!=None

    try:
        opts, args = getopt.getopt(sys.argv[1:], "hi:d:o:")
    except getopt.GetoptError, e:
        usage(e.msg)

    for o, a in opts:
        if o == '-h': usage(None)
        elif o == '-i': iname = a
        elif o == '-d': dname = a
        elif o == '-o': oname = a

    if iname:
        print 'Input image:', iname
    else:
        usage('No input image specified!')

    if dname:
        print 'Data file:', dname

    if oname:
        print 'Output image:', oname

    process(iname, dname, oname)


if __name__ == '__main__':
    main()


 类似资料:
  • 问题内容: 我在不知道相应图像的宽度/高度的情况下将标签放入文档中: 我想使用CSS将图像缩放到其“本机”大小(基础图像的大小)的一半。我不知道该怎么做。 使用将相对于包含块而不是图像的大小。 我无法调整为特定的像素宽度,因为我不知道图像的尺寸。 由于我只需要支持WebKit,因此我尝试使用转换: 这样可以很好地调整图像,但不会调整图像元素本身的大小。 @Radagaisus建议使用Javascr

  • 我想保存图像而不压缩它,并希望以其原始形式保存它,即当图像被压缩时,图像大小减小,图像变小。我使用原生相机为此目的。我在Android Studio工作。我正在制作一个应用程序,其中我使用相机来保存图像。但是图像被压缩,非常小,质量非常低。 下面是我保存图像的代码 更新1 为了更好地理解,我将我的方法 我搜索了解决方案,发现我可以使用AndroidBitmapUtil类,所以我复制并粘贴了这个类到

  • 问题内容: 与数据库中的图像进行比较的最佳方法是什么?我试图比较它们(@Image是Image类型): 但是收到错误“数据类型image和image在等于运算符中不兼容”。 问题答案: 由于IMO图像数据类型是二进制数据,并且存储数据的空间很大,因此比较图像字段的最简单方法是哈希比较。因此,您需要在表上存储“照片”列的哈希值。

  • 问题内容: 我有一个原始图像,其中每个像素对应一个16位无符号整数。我正在尝试使用PIL Image.fromstring()函数进行读取,如以下代码所示: PIL文档通知fromstring()函数的第一个参数为’mode’。但是,在查阅文档并进行谷歌搜索时,我无法找到有关该参数真正含义的详细信息(我相信它与色彩空间或类似的东西有关)。有谁知道我在哪里可以找到有关fromstring()函数以及

  • 我的应用程序中有一个椅子的ImageView对象。我有一个库,我想使用,并需要图像是BGR888图像格式。 null

  • 我已经使用这个带有Azure函数和NodeJS文章的背景图像缩略图处理来创建一个缩略图。已成功创建映像。但是图像的尺寸增加了。这是怎么发生的?它一定很小不是吗?我该如何解决这个奇怪的问题? 这是Blob存储器上的原始图像 处理后(缩略图) 这是 Azure 函数(节点):