1. 提取出错
- 首先检查嵌入时的像素值是否越界(0-255),如果越界则在提取的时候无法正确提取
- 嵌入的时候注意整数除法和浮点数除法向下取整结果不一样,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. 代码复现流程
- 灰度图尽量用
pgm
格式 - 开始的时候就分好数据集split_dataset,train:valid:test=6:2:2,SRM隐写分析是5:5
- 文件夹命名用
数字_名字
,比如00_预处理
。所有数据命名要规范,统一。目前主要用到的有数据集(命名规范:数据集_方法_容量_其他属性
),代码(能用Git的尽量用),结果(腾讯文档) - 绘制要做的实验流程图(代码),保存状态,输入和输出路径,日期,统计数据(notion数据库),尽量整理成工作流