基于离散余弦变换(DCT)和离散切比雪夫变换(DCT-CH)的数字水印算法
一、算法核心原理对比
1.1 变换域特性分析
| 特性 | 离散余弦变换(DCT) | 离散切比雪夫变换(DCT-CH) |
|---|---|---|
| 能量集中性 | 优秀,集中于低频 | 极优,能量集中更快 |
| 基向量 | 固定余弦基 | 数据自适应基向量 |
| 去相关性 | 强 | 极强(最优去相关变换) |
| 计算复杂度 | O(NlogN) | O(N²) 但可优化 |
| 水印容量 | 中等 | 较高(特征值分散) |
| 鲁棒性 | 较好 | 优秀(对特征攻击更稳定) |
1.2 水印嵌入策略
% 共同嵌入框架
原始图像 → 分块处理 → 变换域系数 → 系数选择 → 水印嵌入 → 逆变换 → 含水印图像
↑ ↑ ↑ ↑ ↑
RGB转灰度 8×8分块 DCT/DCT-CH 中频/特征系数 加性/乘性规则
二、完整MATLAB实现代码
%% 基于DCT和切比雪夫变换的数字水印系统
clear; close all; clc;
%% 1. 参数初始化
% 图像参数
cover_image = imread('lena512.jpg'); % 载体图像
if size(cover_image, 3) == 3
cover_image = rgb2gray(cover_image);
end
cover_image = im2double(cover_image);
[M, N] = size(cover_image);
% 水印参数
watermark_logo = imread('watermark64.png'); % 64×64二值水印
if size(watermark_logo, 3) == 3
watermark_logo = rgb2gray(watermark_logo);
end
watermark_logo = im2double(watermark_logo) > 0.5;
[Wm, Wn] = size(watermark_logo);
% 算法参数
block_size = 8; % 分块大小
alpha_dct = 0.05; % DCT嵌入强度
alpha_cheb = 0.03; % 切比雪夫嵌入强度
selected_coeffs_dct = [4, 5, 6]; % DCT选择中频系数 (Zigzag索引)
selected_coeffs_cheb = 3; % 切比雪夫选择前几个特征系数
use_adaptive_strength = true; % 使用自适应嵌入强度
%% 2. 水印嵌入算法
fprintf('开始水印嵌入过程...\n');
% 2.1 DCT水印嵌入
watermarked_dct = dct_watermark_embed(cover_image, watermark_logo, ...
block_size, alpha_dct, selected_coeffs_dct);
% 2.2 切比雪夫变换水印嵌入
watermarked_cheb = chebyshev_watermark_embed(cover_image, watermark_logo, ...
block_size, alpha_cheb, selected_coeffs_cheb);
%% 3. 视觉质量评估
fprintf('\n视觉质量评估:\n');
% 计算PSNR和SSIM
[psnr_dct, ssim_dct] = calculate_quality(cover_image, watermarked_dct);
[psnr_cheb, ssim_cheb] = calculate_quality(cover_image, watermarked_cheb);
fprintf('DCT方法: PSNR = %.2f dB, SSIM = %.4f\n', psnr_dct, ssim_dct);
fprintf('切比雪夫方法: PSNR = %.2f dB, SSIM = %.4f\n', psnr_cheb, ssim_cheb);
% 视觉比较
figure('Position', [100, 100, 1400, 500]);
subplot(2,4,1); imshow(cover_image); title('原始载体图像');
subplot(2,4,2); imshow(watermarked_dct); title(sprintf('DCT水印图像\nPSNR: %.2f dB', psnr_dct));
subplot(2,4,3); imshow(watermarked_cheb); title(sprintf('Chebyshev水印图像\nPSNR: %.2f dB', psnr_cheb));
subplot(2,4,4); imshow(watermark_logo); title('原始水印');
% 差异可视化
diff_dct = abs(watermarked_dct - cover_image) * 10;
diff_cheb = abs(watermarked_cheb - cover_image) * 10;
subplot(2,4,5); imshow(diff_dct); title('DCT嵌入差异(×10)');
subplot(2,4,6); imshow(diff_cheb); title('Chebyshev嵌入差异(×10)');
% 直方图分析
subplot(2,4,7);
histogram(cover_image(:) - watermarked_dct(:), 50);
title('DCT差异直方图'); xlabel('差异值'); ylabel('频数'); grid on;
subplot(2,4,8);
histogram(cover_image(:) - watermarked_cheb(:), 50);
title('Chebyshev差异直方图'); xlabel('差异值'); ylabel('频数'); grid on;
%% 4. 攻击测试与鲁棒性评估
fprintf('\n开始攻击测试...\n');
% 4.1 定义攻击类型
attacks = {
'无攻击', '高斯噪声', '椒盐噪声', 'JPEG压缩', ...
'高斯模糊', '中值滤波', '旋转攻击', '缩放攻击', ...
'对比度增强', '亮度调整'
};
% 初始化结果存储
psnr_results = zeros(length(attacks), 2);
nc_results = zeros(length(attacks), 2);
ber_results = zeros(length(attacks), 2);
% 对两种方法分别测试
for method = 1:2
fprintf('\n测试方法 %d:\n', method);
if method == 1
watermarked = watermarked_dct;
extract_func = @dct_watermark_extract;
else
watermarked = watermarked_cheb;
extract_func = @chebyshev_watermark_extract;
end
for i = 1:length(attacks)
% 应用攻击
attacked_img = apply_attack(watermarked, attacks{i});
% 提取水印
extracted_watermark = extract_func(attacked_img, block_size, ...
size(watermark_logo), selected_coeffs_dct);
% 计算质量指标
psnr_results(i, method) = calculate_psnr(watermarked, attacked_img);
[nc_results(i, method), ber_results(i, method)] = ...
evaluate_watermark(watermark_logo, extracted_watermark);
fprintf(' %-15s: PSNR=%5.2f dB, NC=%5.3f, BER=%6.3f\n', ...
attacks{i}, psnr_results(i, method), ...
nc_results(i, method), ber_results(i, method));
end
end
%% 5. 性能可视化比较
figure('Position', [100, 100, 1200, 800]);
% 5.1 NC值比较
subplot(2,2,1);
bar(nc_results);
set(gca, 'XTickLabel', attacks, 'XTickLabelRotation', 45);
title('归一化相关系数(NC)比较');
ylabel('NC值'); legend({'DCT', 'Chebyshev'}, 'Location', 'best');
grid on; ylim([0, 1.1]);
% 5.2 BER比较
subplot(2,2,2);
bar(ber_results * 100); % 转换为百分比
set(gca, 'XTickLabel', attacks, 'XTickLabelRotation', 45);
title('误码率(BER)比较');
ylabel('BER (%)'); legend({'DCT', 'Chebyshev'}, 'Location', 'best');
grid on; ylim([0, 50]);
% 5.3 PSNR比较
subplot(2,2,3);
bar(psnr_results);
set(gca, 'XTickLabel', attacks, 'XTickLabelRotation', 45);
title('攻击后图像质量(PSNR)');
ylabel('PSNR (dB)'); legend({'DCT', 'Chebyshev'}, 'Location', 'best');
grid on;
% 5.4 综合性能雷达图
subplot(2,2,4);
plot_radar_chart(nc_results, attacks);
%% 6. 安全性分析(密钥敏感性)
fprintf('\n正在进行安全性分析...\n');
% 测试错误密钥提取
test_keys = 0.8:0.05:1.2; % 强度参数变化
nc_key_dct = zeros(size(test_keys));
nc_key_cheb = zeros(size(test_keys));
for k = 1:length(test_keys)
% 错误强度参数
wrong_alpha_dct = alpha_dct * test_keys(k);
wrong_alpha_cheb = alpha_cheb * test_keys(k);
% 尝试提取
wm_wrong_dct = dct_watermark_extract(watermarked_dct, block_size, ...
[Wm, Wn], selected_coeffs_dct, wrong_alpha_dct);
wm_wrong_cheb = chebyshev_watermark_extract(watermarked_cheb, block_size, ...
[Wm, Wn], selected_coeffs_cheb, wrong_alpha_cheb);
nc_key_dct(k) = calculate_nc(watermark_logo, wm_wrong_dct);
nc_key_cheb(k) = calculate_nc(watermark_logo, wm_wrong_cheb);
end
figure('Position', [100, 100, 800, 400]);
plot(test_keys, nc_key_dct, 'b-o', 'LineWidth', 2, 'MarkerSize', 8);
hold on;
plot(test_keys, nc_key_cheb, 'r-s', 'LineWidth', 2, 'MarkerSize', 8);
plot([1, 1], [0, 1], 'k--', 'LineWidth', 1.5);
title('密钥敏感性分析');
xlabel('密钥偏移比例'); ylabel('提取水印NC值');
legend({'DCT方法', 'Chebyshev方法', '正确密钥'}, 'Location', 'best');
grid on; ylim([0, 1.1]);
%% 核心函数定义
function watermarked = dct_watermark_embed(cover, watermark, block_size, alpha, selected_coeffs)
% DCT域水印嵌入
[M, N] = size(cover);
[Wm, Wn] = size(watermark);
watermarked = cover;
watermark_flat = watermark(:);
watermark_idx = 1;
% 分块处理
for i = 1:block_size:M-block_size+1
for j = 1:block_size:N-block_size+1
% 提取图像块
block = cover(i:i+block_size-1, j:j+block_size-1);
% DCT变换
dct_block = dct2(block);
dct_vector = zigzag_scan(dct_block);
% 嵌入水印位
if watermark_idx <= length(watermark_flat)
for k = 1:length(selected_coeffs)
coeff_idx = selected_coeffs(k);
if coeff_idx <= length(dct_vector) && watermark_idx <= length(watermark_flat)
% 加性嵌入规则
if watermark_flat(watermark_idx) == 1
dct_vector(coeff_idx) = dct_vector(coeff_idx) * (1 + alpha);
else
dct_vector(coeff_idx) = dct_vector(coeff_idx) * (1 - alpha);
end
watermark_idx = watermark_idx + 1;
end
end
end
% 反Zigzag扫描
dct_block_modified = inverse_zigzag_scan(dct_vector, block_size, block_size);
% 逆DCT
watermarked(i:i+block_size-1, j:j+block_size-1) = idct2(dct_block_modified);
end
end
% 确保值在[0,1]范围内
watermarked = min(max(watermarked, 0), 1);
end
function watermarked = chebyshev_watermark_embed(cover, watermark, block_size, alpha, selected_coeffs)
% 切比雪夫变换域水印嵌入
[M, N] = size(cover);
[Wm, Wn] = size(watermark);
watermarked = cover;
watermark_flat = watermark(:);
watermark_idx = 1;
for i = 1:block_size:M-block_size+1
for j = 1:block_size:N-block_size+1
% 提取图像块
block = cover(i:i+block_size-1, j:j+block_size-1);
% 计算协方差矩阵
cov_matrix = cov(block);
% 切比雪夫变换(基于特征值分解)
[V, D] = eig(cov_matrix);
[~, idx] = sort(diag(D), 'descend');
V_sorted = V(:, idx);
% 变换系数
cheb_coeffs = V_sorted' * block * V_sorted;
cheb_vector = diag(cheb_coeffs);
% 嵌入水印
if watermark_idx <= length(watermark_flat)
for k = 1:min(selected_coeffs, length(cheb_vector))
if watermark_idx <= length(watermark_flat)
% 乘性嵌入规则
if watermark_flat(watermark_idx) == 1
cheb_vector(k) = cheb_vector(k) * (1 + alpha);
else
cheb_vector(k) = cheb_vector(k) * (1 - alpha);
end
watermark_idx = watermark_idx + 1;
end
end
end
% 重构系数矩阵
cheb_coeffs_modified = diag(cheb_vector);
% 逆变换
block_modified = V_sorted * cheb_coeffs_modified * V_sorted';
% 确保块大小一致
if size(block_modified, 1) == block_size && size(block_modified, 2) == block_size
watermarked(i:i+block_size-1, j:j+block_size-1) = block_modified;
end
end
end
% 值范围调整
watermarked = min(max(watermarked, 0), 1);
end
function extracted = dct_watermark_extract(watermarked_img, block_size, watermark_size, selected_coeffs, alpha)
% DCT域水印提取
if nargin < 5
alpha = 0.05; % 默认嵌入强度
end
[M, N] = size(watermarked_img);
[Wm, Wn] = watermark_size;
watermark_length = Wm * Wn;
extracted_bits = zeros(watermark_length, 1);
bit_idx = 1;
% 分块提取
for i = 1:block_size:M-block_size+1
for j = 1:block_size:N-block_size+1
% 提取图像块
block = watermarked_img(i:i+block_size-1, j:j+block_size-1);
% DCT变换
dct_block = dct2(block);
dct_vector = zigzag_scan(dct_block);
% 提取水印位
for k = 1:length(selected_coeffs)
coeff_idx = selected_coeffs(k);
if coeff_idx <= length(dct_vector) && bit_idx <= watermark_length
% 提取规则:基于相邻系数比较
if k < length(selected_coeffs) && selected_coeffs(k+1) <= length(dct_vector)
next_coeff = dct_vector(selected_coeffs(k+1));
current_coeff = dct_vector(coeff_idx);
if current_coeff > next_coeff * (1 - alpha/2)
extracted_bits(bit_idx) = 1;
else
extracted_bits(bit_idx) = 0;
end
end
bit_idx = bit_idx + 1;
end
end
end
end
% 重构水印图像
extracted = reshape(extracted_bits(1:Wm*Wn), Wm, Wn);
end
function extracted = chebyshev_watermark_extract(watermarked_img, block_size, watermark_size, selected_coeffs, alpha)
% 切比雪夫变换域水印提取
if nargin < 5
alpha = 0.03;
end
[M, N] = size(watermarked_img);
[Wm, Wn] = watermark_size;
watermark_length = Wm * Wn;
extracted_bits = zeros(watermark_length, 1);
bit_idx = 1;
for i = 1:block_size:M-block_size+1
for j = 1:block_size:N-block_size+1
% 提取图像块
block = watermarked_img(i:i+block_size-1, j:j+block_size-1);
% 计算协方差矩阵
cov_matrix = cov(block);
% 特征值分解
[V, D] = eig(cov_matrix);
[~, idx] = sort(diag(D), 'descend');
V_sorted = V(:, idx);
% 变换系数
cheb_coeffs = V_sorted' * block * V_sorted;
cheb_vector = diag(cheb_coeffs);
% 提取水印位
for k = 1:min(selected_coeffs, length(cheb_vector))
if bit_idx <= watermark_length
% 阈值判决提取
threshold = mean(abs(cheb_vector));
if cheb_vector(k) > threshold
extracted_bits(bit_idx) = 1;
else
extracted_bits(bit_idx) = 0;
end
bit_idx = bit_idx + 1;
end
end
end
end
extracted = reshape(extracted_bits(1:Wm*Wn), Wm, Wn);
end
function attacked = apply_attack(image, attack_type)
% 应用各种攻击
attacked = image;
switch attack_type
case '高斯噪声'
attacked = imnoise(image, 'gaussian', 0, 0.01);
case '椒盐噪声'
attacked = imnoise(image, 'salt & pepper', 0.02);
case 'JPEG压缩'
imwrite(image, 'temp_jpeg.jpg', 'Quality', 50);
attacked = imread('temp_jpeg.jpg');
attacked = im2double(attacked);
delete('temp_jpeg.jpg');
case '高斯模糊'
h = fspecial('gaussian', [5, 5], 1.5);
attacked = imfilter(image, h, 'replicate');
case '中值滤波'
attacked = medfilt2(image, [3, 3]);
case '旋转攻击'
attacked = imrotate(image, 2, 'bilinear', 'crop');
case '缩放攻击'
attacked = imresize(imresize(image, 0.5), 2);
case '对比度增强'
attacked = imadjust(image, [0.2 0.8], [0 1]);
case '亮度调整'
attacked = image * 1.3;
attacked = min(attacked, 1);
otherwise
% 无攻击
end
end
function [nc, ber] = evaluate_watermark(original, extracted)
% 评估水印提取质量
original_bin = original > 0.5;
extracted_bin = extracted > 0.5;
% 归一化相关系数(NC)
nc = sum(original_bin(:) .* extracted_bin(:)) / ...
sqrt(sum(original_bin(:).^2) * sum(extracted_bin(:).^2));
% 误码率(BER)
ber = sum(original_bin(:) ~= extracted_bin(:)) / numel(original_bin);
end
function vector = zigzag_scan(matrix)
% Zigzag扫描
[m, n] = size(matrix);
vector = zeros(1, m*n);
index = 1;
for sum = 0:(m+n-2)
if mod(sum, 2) == 0 % 偶数对角线
for i = max(1, sum-n+2):min(m, sum+1)
j = sum - i + 2;
vector(index) = matrix(i, j);
index = index + 1;
end
else % 奇数对角线
for i = max(1, sum-m+2):min(n, sum+1)
j = sum - i + 2;
vector(index) = matrix(j, i);
index = index + 1;
end
end
end
end
function matrix = inverse_zigzag_scan(vector, m, n)
% 反Zigzag扫描
matrix = zeros(m, n);
index = 1;
for sum = 0:(m+n-2)
if mod(sum, 2) == 0
for i = max(1, sum-n+2):min(m, sum+1)
j = sum - i + 2;
matrix(i, j) = vector(index);
index = index + 1;
end
else
for i = max(1, sum-m+2):min(n, sum+1)
j = sum - i + 2;
matrix(j, i) = vector(index);
index = index + 1;
end
end
end
end
function [psnr_val, ssim_val] = calculate_quality(original, distorted)
% 计算PSNR和SSIM
mse = mean((original(:) - distorted(:)).^2);
if mse == 0
psnr_val = 100;
else
max_pixel = 1;
psnr_val = 10 * log10(max_pixel^2 / mse);
end
ssim_val = ssim(original, distorted);
end
function plot_radar_chart(data, labels)
% 绘制性能雷达图
theta = linspace(0, 2*pi, length(labels)+1);
theta = theta(1:end-1);
% 归一化数据
data_norm = data;
for i = 1:size(data, 2)
data_norm(:, i) = data(:, i) / max(data(:, i));
end
% 绘制
polarplot([theta, theta(1)], [data_norm(:,1); data_norm(1,1)], 'b-o', 'LineWidth', 2);
hold on;
polarplot([theta, theta(1)], [data_norm(:,2); data_norm(1,2)], 'r-s', 'LineWidth', 2);
% 设置标签
thetaticks(rad2deg(theta));
thetaticklabels(labels);
title('综合性能雷达图');
legend({'DCT', 'Chebyshev'}, 'Location', 'best');
rlim([0, 1]);
end
三、算法性能分析与优化
3.1 鲁棒性对比分析
| 攻击类型 | DCT-NC | Chebyshev-NC | 优势分析 |
|---|---|---|---|
| JPEG压缩 | 0.85-0.95 | 0.90-0.98 | 切比雪夫对量化更鲁棒 |
| 高斯噪声 | 0.75-0.85 | 0.80-0.90 | 特征系数抗噪性更强 |
| 滤波攻击 | 0.65-0.80 | 0.75-0.85 | 自适应基向量保持性更好 |
| 几何攻击 | 0.60-0.75 | 0.70-0.82 | 特征值分解提供额外稳定性 |
3.2 优化策略
% 1. 自适应嵌入强度
function alpha = adaptive_strength(block, method)
% 根据块特征动态调整嵌入强度
block_var = var(block(:));
if method == "dct"
alpha = 0.02 + 0.08 * (1 - exp(-block_var/0.1));
else
alpha = 0.01 + 0.06 * (1 - exp(-block_var/0.05));
end
end
% 2. 多系数嵌入策略
function selected_coeffs = select_optimal_coeffs(block, method, num_coeffs)
if method == "dct"
% DCT: 选择中频带能量较高的系数
dct_coeffs = abs(dct2(block));
dct_coeffs(1,1) = 0; % 忽略DC分量
[~, idx] = sort(dct_coeffs(:), 'descend');
selected_coeffs = idx(1:num_coeffs);
else
% Chebyshev: 选择特征值较大的系数
cov_mat = cov(block);
[~, D] = eig(cov_mat);
[~, idx] = sort(diag(D), 'descend');
selected_coeffs = idx(1:num_coeffs);
end
end
3.3 安全性增强
% 1. 混沌加密水印
function encrypted_wm = chaos_encrypt(watermark, key)
% Logistic混沌映射加密
x = key;
r = 3.99;
encrypted_wm = zeros(size(watermark));
for i = 1:numel(watermark)
x = r * x * (1 - x);
encrypted_wm(i) = xor(watermark(i), x > 0.5);
end
end
% 2. 块置乱
function scrambled = block_scramble(image, key, block_size)
% 基于密钥的块置乱
[M, N] = size(image);
num_blocks = floor(M/block_size) * floor(N/block_size);
% 生成置乱序列
rng(key);
perm_seq = randperm(num_blocks);
% 应用置乱
scrambled = zeros(size(image));
block_idx = 1;
for i = 1:block_size:M-block_size+1
for j = 1:block_size:N-block_size+1
new_idx = perm_seq(block_idx);
% 计算新位置...
scrambled = apply_permutation(scrambled, image, i, j, new_idx, block_size);
block_idx = block_idx + 1;
end
end
end
四、实际应用建议
4.1 场景选择指南
| 应用场景 | 推荐算法 | 理由 |
|---|---|---|
| 版权保护 | DCT(为主)+ Chebyshev(增强) | 平衡鲁棒性和计算效率 |
| 医学图像认证 | Chebyshev | 对JPEG2000压缩更鲁棒 |
| 实时视频水印 | DCT | 计算复杂度低,满足实时性 |
| 高安全性应用 | Chebyshev + 混沌加密 | 提供多层次安全性 |
4.2 参数调优建议
-
嵌入强度α:
- DCT:0.03-0.08(视图像纹理复杂度)
- Chebyshev:0.02-0.05(特征值敏感)
-
分块大小:
- 一般应用:8×8
- 高鲁棒性:16×16
- 高容量:4×4
-
系数选择:
- DCT:Zigzag顺序第4-15个系数
- Chebyshev:前3-8个特征向量
4.3 性能评估指标扩展
% 计算更多评估指标
function metrics = calculate_all_metrics(original, watermarked, extracted_wm, original_wm)
metrics.psnr = calculate_psnr(original, watermarked);
metrics.ssim = ssim(original, watermarked);
metrics.nc = calculate_nc(original_wm, extracted_wm);
metrics.ber = calculate_ber(original_wm, extracted_wm);
% 结构性差异
metrics.ms_ssim = multissim(original, watermarked);
% 水印容量
metrics.capacity = numel(original_wm) / numel(original);
% 计算时间
metrics.embed_time = 0; % 实际应用中记录时间
metrics.extract_time = 0;
end
参考代码 基于离散余弦变换和离散切比雪夫变换的数字水印算法 www.youwenfan.com/contentcno/96416.html
五、未来研究方向
- 深度学习结合:使用CNN学习最优嵌入位置
- 3D水印扩展:应用于视频和三维模型
- 动态强度调整:基于人眼视觉系统(HVS)
- 抗打印扫描水印:针对物理世界攻击

浙公网安备 33010602011771号