【论文复现】图像隐写常见问题

1. 提取出错

  1. 首先检查嵌入时的像素值是否越界(0-255),如果越界则在提取的时候无法正确提取
  2. 嵌入的时候注意整数除法和浮点数除法向下取整结果不一样,floor(int(10)/16)=1,floor(double(10)/16)=0

Image.open()和cv2.imread()的区别

python的PIL.Image.open(),是以 (w, h) 即“宽 x 高”的方式读取图片,数据类型是PIL.Image.Image,如果将其转换为numpy.ndarray,格式为 (h, w, c) 即“高 x 宽 x 通道”;如果将其转换为torch.Tensor,格式为 (c, h, w) 即“通道 x 高 x 宽”——像素顺序都是 RGB

使用cv2.imread(),是以 (h, w, c) 即“高 x 宽 x 通道”的方式读取图片,数据类型是numpy.ndarray;如果将其转换为torch.Tensor,格式为 (c, h, w) 即“通道 x 高 x 宽”——像素顺序都是BGR

参考链接:https://zhuanlan.zhihu.com/p/402833064

2. 常用代码部分

1.生成随机二进制数

% create and save msg  **matlab**
message = randi([0,1],1024,1);
save 'Catalan-based-Steganography\msg_1024bit.mat' message;

load("msg_256bit.mat");

2. numpy和pandas库的使用(ndarray和dataframe) 待完善

一个ndarray只能保存同一个类型的数据,比如都是float
dataframe可以保存不同类型,比如字符串,数字

都是数字的表可以用ndarray,后边有补充信息再转为dataframe添加进去

# 初始化
stacked_array = np.zeros(2,) # 生成一行2列的一维ndarray
stacked_array = np.zeros(2,1) # 生成一行2列的二维ndarray

all_pt_list = pd.DataFrame(stacked_array)

# 增
stacked_array = np.vstack([stacked_array, column_means]) # 垂直方向拼接stacked_array和column_means
all_list = np.concatenate(
        (ACC_LIST.reshape(-1, 1), ALL_JPEG_LIST, ALL_guassian_LIST, ALL_blur_LIST),
        axis=1,
    )  # axis=1在左右方向上拼接

df.insert(0, "epoch", epoch_list) # 在第0列插入列名epoch,数据是epoch_list

# 删

# 改

# 查
column_means = df.mean() #  计算df每一列的平均值


# 保留几位小数 
stacked_array = np.around(stacked_array, 4) # 保留四位小数


# 保存到文件
df.to_csv(f"0302_noise_all_pt_delta_0.csv", index=False)


# 互相转换
column_means = column_means.to_numpy() # df转ndarray


2. 遍历文件

%% matlab
cover_path =  'D:\database\BOSSbase_1.01_png\';% 图像文件夹路径
img_path_list = dir(strcat(cover_path,'*.png'));%获取该文件夹中所有PNG格式的图像
[~,ind] = natsort({img_path_list.name}); % 自然语序
img_path_list = img_path_list(ind);
img_num = length(img_path_list);%获取图像总数量
if img_num > 0 %有满足条件的图像
    for img_idx = 1:10 %逐一读取图像
        disp(img_idx);
        image_name = img_path_list(img_idx).name;% 图像名
        gray_img =  imread(strcat(cover_path,image_name));
        imwrite(stego,strcat(stego_path,num2str(img_idx),'.pgm')); % save
    end
end
## python 

import os
from natsort import natsorted
import csv

#------------创建文件夹--------------start
path = "/home/user/Documents/"
folder_name = "new_folder"
os.mkdir(os.path.join(path, folder_name))
#-----------创建文件夹--------------end

train_path = r'/home/train' # 按照自然排序遍历文件夹
file_list = natsorted(os.listdir(train_path))
selected_files = file_list[10:200] # 选取序号为200-210的文件名

for file in selected_files :
    print(file)
    fea_train = pd.read_csv(train_path +'/'+ file, header=None,delimiter=' ')
    

3. 找遗漏的文件

## python
import csv
import os
from natsort import natsorted

folder_path = '/home/database/BOSS_all/BOSSbase_1.01'# 指定完整文件夹路径
file_names = [f.name for f in os.scandir(folder_path) if f.is_file()]# 获取指定文件夹下的所有文件名
sorted_image_files = natsorted(file_names) # 对文件名进行自然排序

sorted_image_files = [x[:-4] for x in sorted_image_files] # 去掉后缀.png
print(sorted_image_files)

# 指定要遍历的文件夹路径
fnns_path = '/home/train'
# 获取指定文件夹下的所有文件名
file_names = [f.name for f in os.scandir(fnns_path) if f.is_file()]
# 对文件名进行自然排序
sorted_fnns_files = natsorted(file_names)
sorted_fnns_files = [x[:-4] for x in sorted_fnns_files] # 去掉后缀.png
print(sorted_fnns_files)

# 求差集
set1 = set(sorted_image_files[:6000])
set2 = set(sorted_fnns_files)
result = list(set1 - set2)
print(result)

4. python多进程调用shell脚本命令 已弃用Linux的SRM (Windows上SRM.exe快很多)

记录一下,以后可能还会用到多进程调用带参数的shell脚本
原因:很多数据集都要跑SRM,6000张图提取特征就14-15小时
下面代码块是单个数据集跑SRM的流程

--------------这是srm_all.sh
#!/bin/bash
# 1. 修改当前路径,后续调用命令
cd /home/SRMQ1_linux_make_v1.1/release 
start_time=$(date +%s)

# 2. 创建一个包含要处理的文件夹的列表
# elements=("BOSSbase_1.01_256_catalan_75_pgm" "BOSSbase_1.01_256_catalan_80_pgm" "BOSSbase_1.01_256_catalan_85_pgm") # 放在database文件夹下
elements=($1) # $1 是取第1个参数 $2 是取第2个参数 这里就可以在调用的时候传参数

# 3. 使用 for 循环遍历列表中的每个元素并执行相应的操作 针对elements中有多个元素的情况,如果只有一个元素,可以去掉for循环
for algorithm in "${elements[@]}"
do
    echo "正在处理 $algorithm"
    # 1. 创建存特征的父文件夹
    create_folder_command="mkdir /home/SRMQ1_linux_make_v1.1/00_srmq1_fea/$algorithm"
    eval "$create_folder_command" # 将字符串转成命令执行
    echo "创建父文件夹结束"

    # 1.1 创建存特征的 train子文件夹
    create_folder_command="mkdir /home/SRMQ1_linux_make_v1.1/00_srmq1_fea/$algorithm/train"
    eval "$create_folder_command"

    # 1.2 创建存特征的test 子文件夹
    create_folder_command="mkdir /home/SRMQ1_linux_make_v1.1/00_srmq1_fea/$algorithm/test"
    eval "$create_folder_command"
    echo "创建子文件夹结束"

    # 2. 提取特征
    command="./SRMQ1 -I /home/00_database/${algorithm}/train -O /home/SRMQ1_linux_make_v1.1/00_srmq1_fea/$algorithm/train -V"

    eval "$command"
    echo "提取train特征结束"

    command="./SRMQ1 -I /home/00_database/${algorithm}/test -O /home/SRMQ1_linux_make_v1.1/00_srmq1_fea/$algorithm/test -V" 
    eval "$command" 
    echo "提取test特征结束" 

    # 3. 组合特征
    # 直接调用python命令
    /home/miniconda3/envs/steganogan/bin/python3 /home/SRMQ1_linux_make_v1.1/01_SubmodelConcatenation/01_submodel.py $algorithm

    # 4. 调用matlab训练

    command="matlab -nodesktop -nosplash -r \"addpath('/home/SRMQ1_linux_make_v1.1/02_train');srm_tra $algorithm '/home/SRMQ1_linux_make_v1.1/01_SubmodelConcatenation/q1_cover_train.csv' '/home/SRMQ1_linux_make_v1.1/01_SubmodelConcatenation/q1_cover_test.csv' '/home/SRMQ1_linux_make_v1.1/01_SubmodelConcatenation/q1_${algorithm}_train.csv' '/home/SRMQ1_linux_make_v1.1/01_SubmodelConcatenation/q1_${algorithm}_test.csv';exit()\""  

    eval "$command"
    echo "$algorithm SRM训练测试结束" 
done

end_time=$(date +%s)
elapsed_time=$((end_time - start_time))

# 转换为分钟和秒数
minutes=$((elapsed_time / 60))
seconds=$((elapsed_time % 60))
# 输出结果
echo "脚本已经运行了 ${minutes} 分钟 ${seconds} 秒。"

下面是多进程实现同时运行多个数据集跑SRM

import multiprocessing
import subprocess

def run_process(function):
    subprocess.call(["./srm_all.sh",function], cwd="/home/hello/workspace/jinghan/SRMQ1_linux_make_v1.1/release") 
    # cwd用于指定运行路径

if __name__ == "__main__":
    processes = []
    functions = [ # 多个进程,只有输入参数不同
        "\"BOSSbase_1.01_1024_catalan_80_pgm\"",  # 注意\是转义字符
        "\"BOSSbase_1.01_1024_catalan_85_pgm\"", 
        "\"BOSSbase_1.01_lsb_256_80_pgm\"",
        "\"BOSSbase_1.01_lsb_256_85_pgm\"",
        "\"BOSSbase_1.01_fnns_256_75_pgm\"",
        "\"BOSSbase_1.01_fnns_256_80_pgm\"",
        "\"BOSSbase_1.01_mean_256_75_pgm\"",
        "\"BOSSbase_1.01_mean_256_80_pgm\"",
    ]

    for function in functions:
        process = multiprocessing.Process(target=run_process, args=(function,)) # 创建进程,target是目标函数,args是run_process的参数,只有一个参数也需要用括号括起来
        processes.append(process) # 把进程加到列表中
        process.start() # 开启进程

    for process in processes:
        process.join() # 主进程等待子进程完成

3. 代码复现流程

  1. 灰度图尽量用pgm格式
  2. 开始的时候就分好数据集split_dataset,train:valid:test=6:2:2,SRM隐写分析是5:5
  3. 文件夹命名用数字_名字,比如00_预处理。所有数据命名要规范,统一。目前主要用到的有数据集(命名规范:数据集_方法_容量_其他属性),代码(能用Git的尽量用),结果(腾讯文档)
  4. 绘制要做的实验流程图(代码),保存状态,输入和输出路径,日期,统计数据(notion数据库),尽量整理成工作流
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岁月漫长_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值