直方图平移与预测误差扩展的可逆水印技术

直方图平移与预测误差扩展的可逆水印技术

这是一种高容量、低失真的可逆水印嵌入技术,适用于需要无损恢复原始载体的领域。

一、核心原理

1.1 技术框架

原始图像 → 像素预测 → 预测误差直方图 → 平移扩展 → 嵌入水印 → 含水印图像
提取过程:含水印图像 → 相同预测 → 预测误差分析 → 提取水印 + 恢复原始图像

1.2 关键概念


二、MATLAB实现代码

2.1 主程序框架

%% 主程序:基于直方图平移和预测误差扩展的可逆水印嵌入
clc; clear; close all;

%% 1. 参数设置
img_path = 'lena.bmp';      % 原始图像
watermark = '秘密信息:这是一段需要隐藏的水印信息!';
block_size = 8;             % 分块大小
threshold_T = 3;            % 直方图平移阈值
use_optimized_prediction = true;  % 使用优化预测器

%% 2. 加载和处理图像
original_img = imread(img_path);
if size(original_img, 3) == 3
    original_img = rgb2gray(original_img);
end
original_img = double(original_img);

[M, N] = size(original_img);
fprintf('图像尺寸: %d × %d\n', M, N);
fprintf('水印信息: %s\n', watermark);
fprintf('水印长度: %d bits\n', length(watermark)*8);

%% 3. 水印预处理
watermark_bits = watermark_to_bits(watermark);
fprintf('水印转换为二进制: %d bits\n', length(watermark_bits));

%% 4. 可逆水印嵌入
[watermarked_img, peak_point, zero_point, location_map] = ...
    embed_watermark_PEE(original_img, watermark_bits, threshold_T, use_optimized_prediction);

%% 5. 水印提取和恢复
[extracted_watermark, recovered_img] = ...
    extract_watermark_PEE(watermarked_img, threshold_T, peak_point, zero_point, location_map, use_optimized_prediction);

%% 6. 评估性能
evaluate_performance(original_img, watermarked_img, recovered_img, watermark, extracted_watermark);

2.2 核心嵌入函数

function [watermarked_img, peak_point, zero_point, location_map] = ...
    embed_watermark_PEE(original_img, watermark_bits, T, optimized)
    % 基于直方图平移和预测误差扩展的水印嵌入
    % 输入:
    %   original_img - 原始图像
    %   watermark_bits - 水印比特序列
    %   T - 阈值
    %   optimized - 是否使用优化预测器
    % 输出:
    %   watermarked_img - 含水印图像
    %   peak_point - 峰值点
    %   zero_point - 零点
    %   location_map - 位置图(记录不可嵌入像素)
    
    [M, N] = size(original_img);
    watermarked_img = original_img;
    
    % 步骤1: 计算预测误差
    [prediction_errors, prediction_map] = compute_prediction_errors(original_img, optimized);
    
    % 步骤2: 构建预测误差直方图
    [error_hist, bin_centers] = compute_error_histogram(prediction_errors);
    
    % 步骤3: 寻找峰值点和零点
    [peak_point, zero_point] = find_peak_zero_points(error_hist, bin_centers, T);
    
    fprintf('峰值点: %d, 零点: %d\n', peak_point, zero_point);
    
    % 步骤4: 生成位置图(标记不可嵌入像素)
    location_map = create_location_map(original_img, prediction_errors, peak_point, zero_point, T);
    
    % 步骤5: 直方图平移
    watermarked_img = histogram_shifting(original_img, prediction_errors, peak_point, zero_point, T);
    
    % 步骤6: 水印嵌入
    watermark_idx = 1;
    watermark_len = length(watermark_bits);
    
    for i = 2:M-1
        for j = 2:N-1
            % 跳过边界像素
            if location_map(i, j) == 1
                continue;  % 不可嵌入像素
            end
            
            % 计算当前像素的预测误差
            if optimized
                pred = optimized_predictor(watermarked_img, i, j);
            else
                pred = median_predictor(watermarked_img, i, j);
            end
            
            current_error = watermarked_img(i, j) - pred;
            
            % 检查是否在嵌入范围内
            if current_error == peak_point
                if watermark_idx <= watermark_len
                    % 嵌入水印
                    b = watermark_bits(watermark_idx);
                    if b == 1
                        watermarked_img(i, j) = watermarked_img(i, j) + 1;
                    end
                    watermark_idx = watermark_idx + 1;
                    
                    if watermark_idx > watermark_len
                        break;
                    end
                end
            end
            
            if watermark_idx > watermark_len
                break;
            end
        end
        
        if watermark_idx > watermark_len
            break;
        end
    end
    
    % 检查是否所有水印都已嵌入
    if watermark_idx <= watermark_len
        warning('水印未完全嵌入!可能需要调整阈值T');
    end
    
    fprintf('嵌入水印比特数: %d/%d\n', watermark_idx-1, watermark_len);
end

2.3 预测误差计算

function [prediction_errors, prediction_map] = compute_prediction_errors(img, optimized)
    % 计算预测误差
    [M, N] = size(img);
    prediction_errors = zeros(M, N);
    prediction_map = zeros(M, N);
    
    % 使用不同的预测器
    for i = 2:M-1
        for j = 2:N-1
            if optimized
                % 优化预测器(GAP: Gradient Adjusted Predictor)
                pred = optimized_predictor(img, i, j);
            else
                % 中值预测器
                pred = median_predictor(img, i, j);
            end
            
            prediction_errors(i, j) = img(i, j) - pred;
            prediction_map(i, j) = pred;
        end
    end
end

function pred = median_predictor(img, i, j)
    % 中值预测器
    neighbors = [img(i-1, j), img(i, j-1), img(i-1, j-1)];
    pred = median(neighbors);
end

function pred = optimized_predictor(img, i, j)
    % 优化预测器(GAP)
    % 考虑梯度信息,提高预测精度
    
    I_n = img(i-1, j);
    I_w = img(i, j-1);
    I_nw = img(i-1, j-1);
    
    % 计算梯度
    dh = abs(I_w - I_nw);
    dv = abs(I_n - I_nw);
    
    if dh - dv > 80
        % 垂直边缘
        pred = I_n;
    elseif dv - dh > 80
        % 水平边缘
        pred = I_w;
    else
        % 平滑区域
        pred = I_w + I_n - I_nw;
        if pred > 255
            pred = 255;
        elseif pred < 0
            pred = 0;
        end
    end
end

2.4 直方图分析与处理

function [peak_point, zero_point] = find_peak_zero_points(error_hist, bin_centers, T)
    % 寻找峰值点和零点
    % 峰值点:直方图中频率最高的点
    % 零点:频率为0或最低的点
    
    % 找到峰值
    [max_freq, peak_idx] = max(error_hist);
    peak_point = bin_centers(peak_idx);
    
    % 在峰值点附近寻找零点
    % 搜索范围:[-T, T]
    search_range = -T:T;
    
    % 从峰值点向两侧搜索
    zero_candidates = [];
    
    for k = 1:length(search_range)
        test_point = peak_point + search_range(k);
        
        % 检查是否在直方图范围内
        idx = find(bin_centers == test_point, 1);
        if ~isempty(idx) && error_hist(idx) == 0
            zero_candidates = [zero_candidates, test_point];
        end
    end
    
    % 如果没有找到零点,选择频率最低的点
    if isempty(zero_candidates)
        [~, min_idx] = min(error_hist);
        zero_point = bin_centers(min_idx);
    else
        % 选择离峰值点最近的零点
        distances = abs(zero_candidates - peak_point);
        [~, min_dist_idx] = min(distances);
        zero_point = zero_candidates(min_dist_idx);
    end
end

function watermarked_img = histogram_shifting(img, prediction_errors, peak, zero, T)
    % 执行直方图平移
    [M, N] = size(img);
    watermarked_img = img;
    
    for i = 2:M-1
        for j = 2:N-1
            error = prediction_errors(i, j);
            
            if zero > peak
                % 零点在峰值右侧
                if error > peak && error < zero
                    watermarked_img(i, j) = watermarked_img(i, j) + 1;
                elseif error >= zero
                    watermarked_img(i, j) = watermarked_img(i, j) + 1;
                end
            else
                % 零点在峰值左侧
                if error < peak && error > zero
                    watermarked_img(i, j) = watermarked_img(i, j) - 1;
                elseif error <= zero
                    watermarked_img(i, j) = watermarked_img(i, j) - 1;
                end
            end
            
            % 确保像素值在有效范围内
            if watermarked_img(i, j) > 255
                watermarked_img(i, j) = 255;
            elseif watermarked_img(i, j) < 0
                watermarked_img(i, j) = 0;
            end
        end
    end
end

2.5 水印提取和恢复

function [extracted_watermark, recovered_img] = ...
    extract_watermark_PEE(watermarked_img, T, peak, zero, location_map, optimized)
    % 提取水印并恢复原始图像
    [M, N] = size(watermarked_img);
    recovered_img = watermarked_img;
    
    % 存储提取的水印比特
    extracted_bits = [];
    
    % 第一遍:提取水印
    for i = 2:M-1
        for j = 2:N-1
            if location_map(i, j) == 1
                continue;
            end
            
            % 计算预测值
            if optimized
                pred = optimized_predictor(watermarked_img, i, j);
            else
                pred = median_predictor(watermarked_img, i, j);
            end
            
            current_error = watermarked_img(i, j) - pred;
            
            % 检查是否是嵌入位置
            if current_error == peak || current_error == peak + 1
                if current_error == peak
                    extracted_bits = [extracted_bits, 0];
                else
                    extracted_bits = [extracted_bits, 1];
                end
                
                % 恢复原始像素值
                if current_error == peak + 1
                    recovered_img(i, j) = recovered_img(i, j) - 1;
                end
            end
        end
    end
    
    % 第二遍:逆直方图平移
    for i = 2:M-1
        for j = 2:N-1
            if location_map(i, j) == 1
                continue;
            end
            
            % 计算预测误差(使用恢复后的图像)
            if optimized
                pred = optimized_predictor(recovered_img, i, j);
            else
                pred = median_predictor(recovered_img, i, j);
            end
            
            error = recovered_img(i, j) - pred;
            
            % 逆平移
            if zero > peak
                if error > peak + 1 && error <= zero
                    recovered_img(i, j) = recovered_img(i, j) - 1;
                elseif error > zero
                    recovered_img(i, j) = recovered_img(i, j) - 1;
                end
            else
                if error < peak - 1 && error >= zero
                    recovered_img(i, j) = recovered_img(i, j) + 1;
                elseif error < zero
                    recovered_img(i, j) = recovered_img(i, j) + 1;
                end
            end
        end
    end
    
    % 将提取的比特转换为水印信息
    extracted_watermark = bits_to_watermark(extracted_bits);
    
    fprintf('提取水印比特数: %d\n', length(extracted_bits));
end

2.6 辅助函数

function bits = watermark_to_bits(watermark_str)
    % 将字符串转换为比特序列
    bits = [];
    for i = 1:length(watermark_str)
        char_bits = dec2bin(double(watermark_str(i)), 8);
        bits = [bits, char_bits - '0'];
    end
end

function watermark_str = bits_to_watermark(bit_seq)
    % 将比特序列转换为字符串
    watermark_str = '';
    
    % 确保比特数是8的倍数
    num_bits = length(bit_seq);
    num_chars = floor(num_bits / 8);
    
    for i = 1:num_chars
        start_idx = (i-1)*8 + 1;
        end_idx = i*8;
        
        if end_idx > num_bits
            break;
        end
        
        char_bits = bit_seq(start_idx:end_idx);
        char_code = bin2dec(num2str(char_bits));
        watermark_str = [watermark_str, char(char_code)];
    end
end

function location_map = create_location_map(img, prediction_errors, peak, zero, T)
    % 创建位置图,标记不可嵌入像素
    [M, N] = size(img);
    location_map = zeros(M, N);
    
    for i = 2:M-1
        for j = 2:N-1
            error = prediction_errors(i, j);
            
            % 标记可能溢出的像素
            if zero > peak
                if img(i, j) == 255 && error >= zero
                    location_map(i, j) = 1;
                end
            else
                if img(i, j) == 0 && error <= zero
                    location_map(i, j) = 1;
                end
            end
            
            % 标记边界像素
            if i == 1 || i == M || j == 1 || j == N
                location_map(i, j) = 1;
            end
        end
    end
end

2.7 性能评估

function evaluate_performance(original_img, watermarked_img, recovered_img, original_watermark, extracted_watermark)
    % 评估算法性能
    
    %% 1. 图像质量评估
    % PSNR (峰值信噪比)
    psnr_wm = psnr(uint8(watermarked_img), uint8(original_img));
    psnr_rec = psnr(uint8(recovered_img), uint8(original_img));
    
    % SSIM (结构相似性)
    ssim_wm = ssim(uint8(watermarked_img), uint8(original_img));
    ssim_rec = ssim(uint8(recovered_img), uint8(original_img));
    
    % MSE (均方误差)
    mse_wm = immse(uint8(watermarked_img), uint8(original_img));
    mse_rec = immse(uint8(recovered_img), uint8(original_img));
    
    %% 2. 水印正确性评估
    watermark_correct = strcmp(original_watermark, extracted_watermark);
    watermark_similarity = sum(original_watermark == extracted_watermark) / length(original_watermark);
    
    %% 3. 容量评估
    [M, N] = size(original_img);
    total_pixels = M * N;
    usable_pixels = sum(sum(original_img(2:end-1, 2:end-1) > 0 & original_img(2:end-1, 2:end-1) < 255));
    
    %% 4. 显示结果
    fprintf('\n========== 性能评估结果 ==========\n');
    
    fprintf('图像质量指标:\n');
    fprintf('  含水印图像 PSNR: %.2f dB\n', psnr_wm);
    fprintf('  恢复图像 PSNR: %.2f dB\n', psnr_rec);
    fprintf('  含水印图像 SSIM: %.4f\n', ssim_wm);
    fprintf('  恢复图像 SSIM: %.4f\n', ssim_rec);
    fprintf('  含水印图像 MSE: %.4f\n', mse_wm);
    fprintf('  恢复图像 MSE: %.4f\n', mse_rec);
    
    fprintf('\n水印正确性:\n');
    fprintf('  水印完全正确: %s\n', string(watermark_correct));
    fprintf('  水印相似度: %.2f%%\n', watermark_similarity*100);
    
    fprintf('\n容量评估:\n');
    fprintf('  图像尺寸: %d × %d = %d 像素\n', M, N, total_pixels);
    fprintf('  可用像素: %d\n', usable_pixels);
    fprintf('  嵌入率: %.4f bpp (比特每像素)\n', length(original_watermark)*8 / total_pixels);
    
    %% 5. 可视化结果
    figure('Position', [100, 100, 1200, 800]);
    
    % 子图1: 原始图像
    subplot(2, 3, 1);
    imshow(uint8(original_img));
    title('原始图像');
    
    % 子图2: 含水印图像
    subplot(2, 3, 2);
    imshow(uint8(watermarked_img));
    title(sprintf('含水印图像\nPSNR=%.2fdB, SSIM=%.4f', psnr_wm, ssim_wm));
    
    % 子图3: 恢复图像
    subplot(2, 3, 3);
    imshow(uint8(recovered_img));
    title(sprintf('恢复图像\nPSNR=%.2fdB, SSIM=%.4f', psnr_rec, ssim_rec));
    
    % 子图4: 差值图像1
    subplot(2, 3, 4);
    diff1 = abs(double(watermarked_img) - double(original_img));
    imshow(uint8(diff1 * 10));  % 放大显示
    title('含水印-原始图像差值(×10)');
    colorbar;
    
    % 子图5: 差值图像2
    subplot(2, 3, 5);
    diff2 = abs(double(recovered_img) - double(original_img));
    imshow(uint8(diff2 * 10));  % 放大显示
    title('恢复-原始图像差值(×10)');
    colorbar;
    
    % 子图6: 水印信息
    subplot(2, 3, 6);
    text(0.1, 0.5, sprintf('原始水印:\n%s\n\n提取水印:\n%s\n\n正确性: %s\n相似度: %.1f%%', ...
        original_watermark, extracted_watermark, ...
        string(watermark_correct), watermark_similarity*100), ...
        'FontSize', 10, 'Interpreter', 'none');
    axis off;
    title('水印信息对比');
    
    sgtitle('直方图平移与预测误差扩展水印算法性能评估');
end

2.8 预测误差直方图分析

function [error_hist, bin_centers] = compute_error_histogram(prediction_errors)
    % 计算预测误差直方图
    
    % 展平预测误差矩阵
    errors_flat = prediction_errors(:);
    
    % 移除零值(未计算的边界)
    errors_flat = errors_flat(errors_flat ~= 0);
    
    % 计算直方图
    min_error = min(errors_flat);
    max_error = max(errors_flat);
    bin_edges = min_error-0.5:1:max_error+0.5;
    
    error_hist = histcounts(errors_flat, bin_edges);
    bin_centers = (bin_edges(1:end-1) + bin_edges(2:end)) / 2;
    
    % 可视化直方图
    figure('Position', [200, 200, 800, 400]);
    
    subplot(1, 2, 1);
    bar(bin_centers, error_hist, 'b');
    xlabel('预测误差值');
    ylabel('频率');
    title('预测误差直方图');
    grid on;
    
    subplot(1, 2, 2);
    % 显示峰值区域
    [max_freq, peak_idx] = max(error_hist);
    peak_value = bin_centers(peak_idx);
    
    % 高亮显示峰值附近区域
    hold on;
    bar(bin_centers, error_hist, 'b');
    
    % 标记峰值
    plot(peak_value, max_freq, 'ro', 'MarkerSize', 10, 'LineWidth', 2);
    text(peak_value, max_freq, sprintf('峰值: %d\n频率: %d', peak_value, max_freq), ...
        'VerticalAlignment', 'bottom', 'HorizontalAlignment', 'center');
    
    xlim([peak_value-10, peak_value+10]);
    xlabel('预测误差值');
    ylabel('频率');
    title('峰值区域放大');
    grid on;
    
    sgtitle('预测误差分布分析');
end

参考代码 利用直方图平移和预测误差拓展的水印嵌入技术 www.youwenfan.com/contentcnu/54958.html

三、算法优化

3.1 自适应阈值选择

function optimal_T = find_optimal_threshold(img, target_capacity)
    % 自适应寻找最优阈值T
    [M, N] = size(img);
    max_capacity = (M-2)*(N-2);  % 最大可能容量
    
    T_values = 1:10;
    capacities = zeros(size(T_values));
    
    for t_idx = 1:length(T_values)
        T = T_values(t_idx);
        
        % 计算预测误差
        prediction_errors = compute_prediction_errors(img, true);
        
        % 计算峰值点频率
        [error_hist, bin_centers] = compute_error_histogram(prediction_errors);
        [max_freq, peak_idx] = max(error_hist);
        peak_point = bin_centers(peak_idx);
        
        % 估计容量
        capacities(t_idx) = max_freq;
    end
    
    % 寻找满足目标容量的最小T
    optimal_T = find(capacities >= target_capacity, 1);
    if isempty(optimal_T)
        optimal_T = T_values(end);
    end
    
    % 可视化容量-T关系
    figure;
    plot(T_values, capacities, 'b-o', 'LineWidth', 2);
    xlabel('阈值 T');
    ylabel('估计容量 (bits)');
    title('容量与阈值关系');
    grid on;
    hold on;
    plot([optimal_T, optimal_T], [0, capacities(optimal_T)], 'r--');
    text(optimal_T, capacities(optimal_T)/2, ...
        sprintf('最优T=%d\n容量=%d bits', optimal_T, capacities(optimal_T)), ...
        'VerticalAlignment', 'bottom');
end

3.2 多峰值嵌入

function [watermarked_img, peaks] = multi_peak_embedding(original_img, watermark_bits)
    % 多峰值嵌入策略,提高容量
    [M, N] = size(original_img);
    
    % 计算预测误差直方图
    prediction_errors = compute_prediction_errors(original_img, true);
    [error_hist, bin_centers] = compute_error_histogram(prediction_errors);
    
    % 寻找多个峰值
    [sorted_freqs, sorted_idx] = sort(error_hist, 'descend');
    num_peaks = min(5, length(sorted_idx));  % 使用前5个峰值
    
    peaks = bin_centers(sorted_idx(1:num_peaks));
    peak_freqs = sorted_freqs(1:num_peaks);
    
    fprintf('找到 %d 个峰值点:\n', num_peaks);
    for i = 1:num_peaks
        fprintf('  峰值%d: 值=%d, 频率=%d\n', i, peaks(i), peak_freqs(i));
    end
    
    % 为每个峰值分配水印比特
    total_capacity = sum(peak_freqs);
    watermark_alloc = round(watermark_bits * peak_freqs / total_capacity);
    
    % 执行多峰值嵌入
    watermarked_img = original_img;
    watermark_idx = 1;
    
    for p = 1:num_peaks
        current_peak = peaks(p);
        bits_to_embed = min(peak_freqs(p), watermark_alloc(p));
        
        % 对该峰值进行嵌入
        for i = 2:M-1
            for j = 2:N-1
                pred = optimized_predictor(watermarked_img, i, j);
                current_error = watermarked_img(i, j) - pred;
                
                if current_error == current_peak
                    if watermark_idx <= length(watermark_bits) && bits_to_embed > 0
                        b = watermark_bits(watermark_idx);
                        if b == 1
                            watermarked_img(i, j) = watermarked_img(i, j) + 1;
                        end
                        watermark_idx = watermark_idx + 1;
                        bits_to_embed = bits_to_embed - 1;
                    end
                end
            end
        end
    end
end

四、应用示例

4.1 医学图像应用

%% 医学图像可逆水印应用
function medical_image_watermarking()
    % 加载医学图像
    medical_img = imread('medical_image.dcm');  % DICOM格式
    
    % 患者信息水印
    patient_info = struct(...
        'name', '张某某', ...
        'id', '2023123456', ...
        'date', '2024-01-15', ...
        'doctor', '李医生', ...
        'diagnosis', '胸部CT扫描正常' ...
    );
    
    % 将结构体转换为字符串
    watermark_str = jsonencode(patient_info);
    
    % 使用更高的T值以获得更大容量
    T = 5;
    
    % 嵌入水印
    [watermarked_img, peak, zero, location_map] = ...
        embed_watermark_PEE(double(medical_img), watermark_to_bits(watermark_str), T, true);
    
    % 保存含水印图像
    imwrite(uint8(watermarked_img), 'medical_image_watermarked.dcm');
    
    fprintf('医学图像水印嵌入完成\n');
    fprintf('患者信息已安全嵌入\n');
end

4.2 批量处理

%% 批量图像水印处理
function batch_watermarking(input_folder, output_folder, watermark)
    % 批量处理文件夹中的所有图像
    
    % 创建输出文件夹
    if ~exist(output_folder, 'dir')
        mkdir(output_folder);
    end
    
    % 获取所有图像文件
    image_files = dir(fullfile(input_folder, '*.bmp'));
    image_files = [image_files; dir(fullfile(input_folder, '*.png'))];
    image_files = [image_files; dir(fullfile(input_folder, '*.jpg'))];
    
    % 处理每张图像
    for i = 1:length(image_files)
        fprintf('处理第 %d/%d 张图像: %s\n', i, length(image_files), image_files(i).name);
        
        % 读取图像
        img_path = fullfile(input_folder, image_files(i).name);
        img = imread(img_path);
        
        if size(img, 3) == 3
            img = rgb2gray(img);
        end
        
        % 嵌入水印
        watermark_bits = watermark_to_bits(watermark);
        T = 3;  % 固定阈值
        
        [watermarked_img, ~, ~, ~] = embed_watermark_PEE(double(img), watermark_bits, T, true);
        
        % 保存结果
        output_path = fullfile(output_folder, image_files(i).name);
        imwrite(uint8(watermarked_img), output_path);
    end
    
    fprintf('批量处理完成!共处理 %d 张图像\n', length(image_files));
end

五、技术特点与优势

5.1 技术特点

  1. 完全可逆:能够无损恢复原始图像
  2. 高容量:利用预测误差扩展提高嵌入容量
  3. 低失真:PSNR通常高于40dB
  4. 安全性:水印信息不可感知
  5. 鲁棒性:对常规图像处理有一定抵抗能力

5.2 性能指标

5.3 适用场景

  1. 医学影像:嵌入患者信息,同时保证诊断质量
  2. 司法取证:嵌入时间戳和取证信息
  3. 军事图像:嵌入加密的元数据
  4. 数字版权:嵌入版权信息,支持所有权验证

六、使用说明

  1. 基本使用

    % 运行主程序
    main_watermarking_PEE
    
  2. 调整参数

    • 修改threshold_T控制嵌入容量和质量
    • 设置use_optimized_prediction选择预测器
    • 调整图像尺寸适应不同应用
  3. 扩展功能

    • 使用多峰值嵌入提高容量
    • 实现自适应阈值选择
    • 添加加密增强安全性

这个实现提供了完整的直方图平移和预测误差扩展水印技术,适用于需要可逆水印的各种应用场景。

专注于matlab/simulink,电子电路,编程