predictor.py import hashlib import cv2 import numpy as np from split import split_blocks, preprocess_pixels # 导入split.py的功能 def checkerboard_partition(block): “”“棋盘格划分灰色/白色像素集合”“” gray_pixels = [] white_pixels = [] for x in range(4): for y in range(4): if (x + y) % 2 == 0: gray_pixels.append(block[x, y]) else: white_pixels.append(block[x, y]) return gray_pixels, white_pixels def diamond_predictor(block): “”“菱形预测器计算预测误差”“” gray_pixels, _ = checkerboard_partition(block) errors = [] for x in range(4): for y in range(4): if (x + y) % 2 == 0: # 仅处理灰色像素 neighbors = [] if x > 0: neighbors.append(block[x - 1, y]) if x < 3: neighbors.append(block[x + 1, y]) if y > 0: neighbors.append(block[x, y - 1]) if y < 3: neighbors.append(block[x, y + 1]) pred = np.round(np.mean(neighbors)) if neighbors else block[x, y] error = block[x, y] - int(pred) errors.append(error) return errors def calculate_embedding_capacity(errors, pk1=-1, pk2=0): “”“计算可嵌入容量V”“” return sum(1 for e in errors if e in {pk1, pk2}) def generate_hash(block, row, col, key): “”“生成8比特认证码”“” # 序列化块数据 block_data = block.tobytes() # 组合输入数据 hash_input = block_data + row.to_bytes(2, ‘big’) + col.to_bytes(2, ‘big’) + key.encode() # 生成SHA-256哈希并取最后1字节(8比特) return hashlib.sha256(hash_input).digest()[-1] --------------------- 完整处理流程 --------------------- def process_image(image_path, key=“secret_key”): # 1. 读取并预处理图像 img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: print(f"错误:无法读取图像 {image_path}") return processed_img, lm = preprocess_pixels(img) blocks, positions, _ = split_blocks(processed_img, block_size=4) # 2. 处理每个子块 results = [] for idx, (block, (row, col)) in enumerate(zip(blocks, positions)): # 步骤1:获取预测误差 errors = diamond_predictor(block) # 步骤2:计算嵌入容量并分类 V = calculate_embedding_capacity(errors) block_type = "DB" if V == 0 else "SB" # 步骤3:生成认证码 ac = generate_hash(block, row // 4, col // 4, key) # 计算块行列索引 # 保存结果 results.append({ "position": (row, col), "type": block_type, "capacity": V, "auth_code": f"{ac:08b}" # 转换为8位二进制字符串 }) # 打印前3块详细信息 if idx < 3: print(f"\n块 {idx + 1} (位置: {row},{col})") print(f"预处理块数据:\n{block}") print(f"预测误差: {errors}") print(f"分类结果: {block_type} (V={V})") print(f"认证码: {results[-1]['auth_code']}") # 3. 统计结果 db_count = sum(1 for r in results if r["type"] == "DB") sb_count = len(results) - db_count print("\n最终统计:") print(f"总块数: {len(results)}") print(f"差分块(DB): {db_count}") print(f"平移块(SB): {sb_count}") print(f"定位表标记数: {sum(lm)}") return results --------------------- 执行验证 --------------------- if name == “main”: # 示例密钥(需与接收方一致) secret_key = “MySecureKey123” # 处理测试图像 results = process_image("pic/test1.bmp", key=secret_key)
时间: 2025-06-26 20:27:50 浏览: 16
这段代码实现了论文《基于分块的高效图像可逆认证方法》中提到的核心功能之一——图像子块的处理,包括子块的分类(差分块和平移块)、认证码的生成等。以下是代码的主要模块解释:
### 主要模块解析
#### `checkerboard_partition` 函数
**作用**: 将一个4x4的图像子块按照棋盘格模式划分为灰色像素集合和白色像素集合。
```python
def checkerboard_partition(block):
gray_pixels = []
white_pixels = []
for x in range(4):
for y in range(4):
if (x + y) % 2 == 0:
gray_pixels.append(block[x, y])
else:
white_pixels.append(block[x, y])
return gray_pixels, white_pixels
```
#### `diamond_predictor` 函数
**作用**: 使用菱形预测器计算每个灰色像素的预测误差。
```python
def diamond_predictor(block):
gray_pixels, _ = checkerboard_partition(block)
errors = []
for x in range(4):
for y in range(4):
if (x + y) % 2 == 0:
neighbors = []
if x > 0: neighbors.append(block[x - 1, y])
if x < 3: neighbors.append(block[x + 1, y])
if y > 0: neighbors.append(block[x, y - 1])
if y < 3: neighbors.append(block[x, y + 1])
pred = np.round(np.mean(neighbors)) if neighbors else block[x, y]
error = block[x, y] - int(pred)
errors.append(error)
return errors
```
#### `calculate_embedding_capacity` 函数
**作用**: 根据预测误差计算子块的可嵌入容量 \( V \),默认使用峰值点 -1 和 0。
```python
def calculate_embedding_capacity(errors, pk1=-1, pk2=0):
return sum(1 for e in errors if e in {pk1, pk2})
```
#### `generate_hash` 函数
**作用**: 生成8比特的认证码(哈希)。
```python
def generate_hash(block, row, col, key):
block_data = block.tobytes()
hash_input = block_data + row.to_bytes(2, 'big') + col.to_bytes(2, 'big') + key.encode()
return hashlib.sha256(hash_input).digest()[-1]
```
#### `process_image` 函数
**作用**: 整合上述各个步骤,处理整个图像,输出每个子块的分类、容量和认证码。
```python
def process_image(image_path, key="secret_key"):
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if img is None:
print(f"错误:无法读取图像 {image_path}")
return
processed_img, lm = preprocess_pixels(img)
blocks, positions, _ = split_blocks(processed_img, block_size=4)
results = []
for idx, (block, (row, col)) in enumerate(zip(blocks, positions)):
errors = diamond_predictor(block)
V = calculate_embedding_capacity(errors)
block_type = "DB" if V == 0 else "SB"
ac = generate_hash(block, row // 4, col // 4, key)
results.append({
"position": (row, col),
"type": block_type,
"capacity": V,
"auth_code": f"{ac:08b}"
})
if idx < 3:
print(f"\n块 {idx + 1} (位置: {row},{col})")
print(f"预处理块数据:\n{block}")
print(f"预测误差: {errors}")
print(f"分类结果: {block_type} (V={V})")
print(f"认证码: {results[-1]['auth_code']}")
db_count = sum(1 for r in results if r["type"] == "DB")
sb_count = len(results) - db_count
print("\n最终统计:")
print(f"总块数: {len(results)}")
print(f"差分块(DB): {db_count}")
print(f"平移块(SB): {sb_count}")
print(f"定位表标记数: {sum(lm)}")
return results
```
### 关键点总结
1. **图像分割与预处理**:使用 `preprocess_pixels` 函数预处理图像,并将图像分割为4x4的小块。
2. **子块分类**:根据预测误差直方图判断子块是差分块还是平移块。
3. **认证码生成**:为每个子块生成唯一的8比特认证码。
4. **统计与打印**:统计各类子块的数量,并打印部分处理细节供调试。
### 运行示例
```python
if __name__ == "__main__":
secret_key = "MySecureKey123"
results = process_image("pic/test1.bmp", key=secret_key)
```
这个脚本可以根据给定路径加载图像,并按照论文中的方法对其进行处理,输出详细的子块分类和认证信息。注意,此代码依赖外部模块 `split.py` 中的 `split_blocks` 和 `preprocess_pixels` 函数,确保它们正确导入并实现相应功能。
阅读全文