images/blog-posts

隐写术・图像隐写术

返回教程主页

上篇 隐写术・图像处理

在了解了一些基本的图像处理操作后,我们开始着手实现图像隐写术。

载入准备的图像

类似信号传输中的调制操作,我们可以把像素值简单的图像作为需要隐藏的图像,而像素值丰富的图像作为载体。

准备一张用于载体的图像「色彩内容可以相对丰富」:

准备一张用需要被隐藏的图像「使用黑白色的文字内容」:

在Python中载入它们:

bg = Image.open('container.jpg')
fg = Image.open('python.jpg')

对载体图像进行预处理

我们需要预处理载体图像为即将被隐藏的内容图像腾出一点点空间。在这里我们将载体图像中的每一个不为偶数的像素值减去一:

def preprocess(frame:Image.Image):
    image = frame.convert('RGB')
    array = np.array(image)
    array -= array % 2
    return array

container = preprocess(bg)

frame.convert('RGB')用于确保输入图像的色彩模式为RGB通道模式。

对内容图像进行二值化

我们将色彩简单的内容图像进行二值化,使之成为像素值仅为0与1的图像:

def to_binary(frame:Image.Image, threshold:int=127):
    gray   = frame.convert('L')
    array  = np.array(gray)
    binary = (array > threshold).astype(np.uint8)
    return binary

binary = to_binary(fg)

frame.convert('L')用于将输入图像转换为灰度图像。

将二值化后的内容载入到载体图像中

在得到处理过的载体图像以及二值化的内容图像后,我们可以将其相加得到最终图像并保存到本地:

def merge_image(container:np.ndarray, binary:np.ndarray):
    r1, c1 = container.shape[0], container.shape[1]
    r2, c2 = binary.shape[0], binary.shape[1]
    r, c = min(r1, r2), min(c1, c2)
    final = np.copy(container)
    final[:r, :c, :] += binary[:r, :c, None]
    return final

final = merge_image(container, binary)
final_img = Image.fromarray(final)
final_img.save('merged.png')

使用png格式存储图像,能够确保图像在被压缩时,隐藏的内容信息不会被抹除,且最终得到的图像文件也不会太大。

尝试从融合后的图像中解析出内容

在完成融合操作后,我们还得通过解析内容来确认操作是否成功:

def get_binary(frame:Image.Image):
    array = np.array(frame)
    array %= 2
    array *= 255
    image = Image.fromarray(array)
    return image

merged = Image.open('merged.png')
_binary = get_binary(merged)
_binary.show()

代码清单

from PIL import Image
import numpy as np


def preprocess(frame:Image.Image):
    image = frame.convert('RGB')
    array = np.array(image)
    array -= array % 2
    return array

def to_binary(frame:Image.Image, threshold:int=127):
    gray   = frame.convert('L')
    array  = np.array(gray)
    binary = (array > threshold).astype(np.uint8)
    return binary

def merge_image(container:np.ndarray, binary:np.ndarray):
    r1, c1 = container.shape[0], container.shape[1]
    r2, c2 = binary.shape[0], binary.shape[1]
    r, c = min(r1, r2), min(c1, c2)
    final = np.copy(container)
    final[:r, :c, :] += binary[:r, :c, None]
    return final

def get_binary(frame:Image.Image):
    array = np.array(frame)
    array %= 2
    array *= 255
    image = Image.fromarray(array)
    return image

bg = Image.open('container.jpg')
fg = Image.open('python.jpg')

container = preprocess(bg)
binary = to_binary(fg)

final = merge_image(container, binary)
final_img = Image.fromarray(final)
final_img.save('merged.png')

merged = Image.open('merged.png')
_binary = get_binary(merged)
_binary.show()

下篇 隐写术・QRCode

SUBSCRIBE


🔒 No spam. Unsubscribe any time.

About kk

kk

Vincenzo Antedoro is an engineer who helps those who want to invest in renewables. For the rest he enjoys teaching with the method of learning by doing..

» More about kk