Skip to content

Commit

Permalink
update codes of mirage_tank
Browse files Browse the repository at this point in the history
  • Loading branch information
guofei9987 committed Jun 2, 2024
1 parent 6153e2c commit feb55b2
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 63 deletions.
35 changes: 22 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ pip install HideInfo
说明
- 已支持彩色图片
- 一般情况下,手机/浏览器的预览和点击大图分别使黑色背景和白色背景,因此有"预览和点击是两张不通的图"的效果
- 短视频:[B站](https://www.bilibili.com/video/BV1DF41117c7/)
- 例子:[example/example_mirage_tank.py](example/example_mirage_tank.py)
- 视频展示:[B站](https://www.bilibili.com/video/BV1DF41117c7/)
- 代码:[example/example_mirage_tank.py](example/example_mirage_tank.py)


```python
from hide_info import mirage_tank
Expand All @@ -60,13 +61,13 @@ mirage_tank.mirage_tank('图片.png', 'img2.jpeg', '幻影坦克.png')
功能:把文件/文本/bytes 类数据,转换为图片
原理:图片 1 个像素的 1 个通道可以存放 0-255 的数字,也就是一个字节。因此可以用来存放数据。
使用场景:
- 信息隐藏、隐蔽传输
- 在只能发送图片的场景下(例如社交软件),发送任意信息
- 信息隐藏、隐蔽传输
- 在只能发送图片的场景下(例如社交软件),发送任意信息

说明
- RGB 3个通道都用来存放数据
- RGB 3个通道都用来存放数据,但不使用透明通道
- 使用前4个字节记录数据的大小,因此要求总的数据量小于 4G
- 可以存放文件、文本、bytes 类数据,把它转化为一张图片
- 可以存放文件、文本、字节等类型的数据,把它转化为一张图片
- 代码:[example_hide_as_img.py](example/example_hide_as_img.py)

```python
Expand All @@ -80,16 +81,16 @@ hide_as_img.file_decode(filename='化物为图-解出来的文件.zip', img_file

## hide_in_img:藏物于图

功能:文件/文本/bytes 类数据,藏进一个 PNG 图片中,并且用肉眼无法看出区别
原理:(LSB算法)根据信息的二进制,改变像素数据的最低位,肉眼是无法察觉这种改变
功能:把文件/文本/字节 类数据,藏进一个预先准备好的 PNG 图片中,使其用肉眼无法看出区别
原理:(LSB算法)根据信息的二进制,改变像素数据的最低位,肉眼是无法察觉这种改变
使用场景:
- 信息隐藏、隐蔽传输
- 在只能发送图片的场景下(例如某社交软件),发送任意信息
- 盲水印、图片溯源、版权保护
- 信息隐藏、隐蔽传输
- 在只能发送图片的场景下(例如某社交软件),发送任意信息
- 盲水印、图片溯源、版权保护


说明
- 解原始数据时,无需原图参与,只看最低位
- 解原始数据时,无需原图参与
- 使用前4个字节存放数据的大小
- 使用位运算,提高一定的性能
- LSB算法对压缩、转格式等攻击脆弱
Expand Down Expand Up @@ -130,6 +131,10 @@ img_watermark.file_decode(img_filename="图片_打入水印.png", wm_extract="

- 例子:[example/example_img_seed.py](example/example_img_seed.py)

原理
- jpg 的内容结束标志为 FF D9,它不关心之后的内容
- rar 的内容开始标志为 52 61 71 21,它不关心前面的内容

## img_exif:把信息隐藏在图片的EXIF中

功能:把信息隐藏在图片的 EXIF 中,从而获得隐蔽信息、传输隐蔽信息的能力
Expand Down Expand Up @@ -176,7 +181,11 @@ hide_as_music.file_decode(filename='化物为音-解出来的文件.zip', wav_fi

## echo_watermark: 回声水印

回声水印(Echo Watermarking)是一种音频水印技术,通过在原始音频信号中添加回声来嵌入信息。这种技术利用了人耳的心理声学特性,即人耳对于短时间内的回声延迟是不敏感的,因此可以将信息隐藏在音频信号的回声中而不影响听感。
人类听觉系统(HAS)极为灵敏,音频感知冗余小,音频水印同时满足隐蔽性和鲁棒性有一定难度。同时音频压缩算法如 MP3 有损压缩有出色的压缩率和音质,对音频水印带来很大的挑战。

掩蔽效应是 HAS 的一个特点:短时间内高能量部分会掩蔽低能量部分,从而让人耳只能听见高能量部分,掩蔽分为超前掩蔽、同时掩蔽、滞后掩蔽。因此可以将信息隐藏在音频信号的回声中而不影响听感。

回声水印(Echo Watermarking)是一种音频水印技术,通过在原始音频信号中添加回声来嵌入信息。

回声水印的实现通常有两个重要参数:回声延迟和回声幅度。延迟时间决定了回声在原始信号之后多久发生,而幅度则影响回声的强度。通过巧妙地调节这两个参数,可以将数字信息(如比特流)编码到音频信号中。

Expand Down
2 changes: 1 addition & 1 deletion example/example_mirage_tank.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from hide_info import mirage_tank

mirage_tank.mirage_tank('图片.jpg', '图片2.png', '幻影坦克.png')
mirage_tank.mirage_tank('图片.jpg', '图片2.png', './output/幻影坦克.png')
2 changes: 1 addition & 1 deletion hide_info/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.1.7'
__version__ = '0.1.9'
67 changes: 19 additions & 48 deletions hide_info/mirage_tank.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,39 @@
'''
原理如下:
- 目标是使得一张PNG图片(带透明涂层),在白色背景下显示图A,在黑色背景下显示图B
- 这样的要求下,可以列出以下方程
aP +(1-a)白 = A
aP + (1-a)黑 = B
已知 白色 = 255,黑色 = 0,代入方程,得到:
a = 1- (A-B)
P = B/a
因为 a 的取值范围为 [0, 1],因此需要 B 图较暗,A图较亮
原理:https://www.guofei.site/2023/08/26/hide_info.html
'''

import cv2
import numpy as np


# 这个只能输出黑白图
def mirage_tank2(img_filename1: str, img_filename2: str, output_img_filename: str):
A = cv2.imread(img_filename1, flags=cv2.IMREAD_GRAYSCALE) / 255
B = cv2.imread(img_filename2, flags=cv2.IMREAD_GRAYSCALE) / 255

# 保证两个图片的大小一致
B = cv2.resize(B, A.shape[::-1])
a = 1 - (A - B)
a = np.clip(a, 0, 1)
P = B / a
P = np.clip(P, 0, 1)

# 创建一个带有透明度通道的图像
image_with_alpha = np.zeros((A.shape[0], A.shape[1], 4), dtype=np.uint8)
image_with_alpha[:, :, 0] = P * 255
image_with_alpha[:, :, 1] = P * 255
image_with_alpha[:, :, 2] = P * 255
image_with_alpha[:, :, 3] = a * 255

# 保存带有透明度通道的图像
cv2.imwrite(output_img_filename, image_with_alpha)
def mirage_tank(img_filename1: str, img_filename2: str, output_img_filename: str, a=0.5, b=None):
img1_rgb = cv2.imread(img_filename1)
img2_grey = cv2.imread(img_filename2, cv2.IMREAD_GRAYSCALE)

# a 越大,img2 越清晰,但是 img1 越可能出现偏差
assert 0.1 < a < 0.95, "0.1 < a < 0.95"
if b is None:
b = max(img1_rgb.mean() - 255 * a, 10)

def mirage_tank(img_filename1: str, img_filename2: str, output_img_filename: str, a=0.5, b=20):
A = cv2.imread(img_filename1)
B = cv2.imread(img_filename2)
img2_grey = a * img2_grey + b

height, width, _ = A.shape
height, width, _ = img1_rgb.shape
# 保证两个图片的大小一致
B = cv2.resize(B, (width, height))
img2_grey = cv2.resize(img2_grey, (width, height))

# 计算 alpha 通道
A_gray = cv2.cvtColor(A, cv2.COLOR_BGR2GRAY)
B_gray = cv2.cvtColor(B, cv2.COLOR_BGR2GRAY)
B_gray = a * B_gray + b # 适当调暗图片B
alpha = 255 - A_gray.astype('int') + B_gray.astype('int')
alpha = np.clip(alpha, 1, 255).reshape(height, width, 1)

# 使用 A 或者 B,决定了彩图来自哪个图
# P = B / (a / 255)
P = (A - (255 - alpha)) / (alpha / 255)
img1_avg = img1_rgb.mean(axis=2)

alpha = 255 - img1_avg.astype('int') + img2_grey.astype('int')
alpha = np.clip(alpha, 0, 255).reshape(height, width, 1)

rgb = (img1_rgb - (255 - alpha)) / (alpha / 255)

alpha = alpha.astype('u8')
P = np.clip(P, 0, 255)
rgb = np.clip(rgb, 0, 255)

# 带有透明度通道的图像
image_with_alpha = np.concatenate([P, alpha], axis=2)
image_with_alpha = np.concatenate([rgb, alpha], axis=2)

cv2.imwrite(output_img_filename, image_with_alpha)

0 comments on commit feb55b2

Please sign in to comment.