基于LSB数字水印的图像篡改检测和恢复完整MATLAB代码
基于LSB数字水印的图像篡改检测和恢复完整MATLAB代码
本文介绍一种基于LSB数字水印的图像篡改检测和恢复方法,并提供完整的MATLAB代码示例。该方法可以有效地定位篡改区域,并利用压缩感知技术恢复篡改后的图像内容。
方法步骤:
- 嵌入水印信息:
- 将给定图像(要求BMP格式,512512大小)划分成88的小块。
- 嵌入水印信息(篡改定位和恢复水印)。
- 篡改图像:
- 对嵌入水印信息的载体图像进行五种不同程度大小的篡改(注意为修改图像内容,但不要改变图像格式)。
- 提取水印信息并检测篡改区域:
- 对篡改之后的图像划分成8*8的小块,每块提取嵌入的水印信息。
- 如果某些图像块提取的水印与其他图像块的不同,则判定为该图像块被篡改。对篡改区域的图像块采用彩色标注。
- 恢复篡改区域:
- 提取恢复水印信息。
- 基于压缩感知恢复篡改区域的内容。
代码示例:
%% 嵌入水印信息
clear; clc; close all;
% 读取载体图像
img = imread('lena.bmp');
figure(1); imshow(img); title('原始图像');
% 将图像划分成8*8的小块
block_size = 8;
[M, N] = size(img);
num_blocks_row = floor(M/block_size);
num_blocks_col = floor(N/block_size);
num_blocks = num_blocks_row * num_blocks_col;
img_blocks = zeros(block_size, block_size, num_blocks);
for i = 1:num_blocks_row
for j = 1:num_blocks_col
img_blocks(:,:,i+(j-1)*num_blocks_row) = img((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size);
end
end
% 嵌入水印信息
watermark = randi([0, 1], num_blocks, 1);
watermark_idx = 1;
for i = 1:num_blocks
block = img_blocks(:,:,i);
lsb = mod(block, 2);
if watermark(watermark_idx) ~= lsb(1)
block(1) = block(1) + (watermark(watermark_idx)-lsb(1));
end
img_blocks(:,:,i) = block;
watermark_idx = watermark_idx + 1;
end
% 合并小块为图像
watermarked_img = zeros(M, N);
for i = 1:num_blocks_row
for j = 1:num_blocks_col
watermarked_img((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size) = img_blocks(:,:,i+(j-1)*num_blocks_row);
end
end
figure(2); imshow(watermarked_img); title('嵌入水印后的图像');
% 保存嵌入水印后的图像
imwrite(watermarked_img, 'watermarked_lena.bmp');
%% 篡改图像并提取水印信息
clear; clc; close all;
% 读取嵌入水印后的图像
img = imread('watermarked_lena.bmp');
figure(1); imshow(img); title('嵌入水印后的图像');
% 计算篡改后的图像
modified_imgs = cell(5,1);
modified_imgs{1} = imnoise(img, 'gaussian', 0, 0.01);
modified_imgs{2} = imnoise(img, 'gaussian', 0, 0.05);
modified_imgs{3} = imnoise(img, 'salt & pepper', 0.01);
modified_imgs{4} = imnoise(img, 'salt & pepper', 0.05);
modified_imgs{5} = imresize(img, 0.5);
% 提取水印信息并检测篡改区域
block_size = 8;
[M, N] = size(img);
num_blocks_row = floor(M/block_size);
num_blocks_col = floor(N/block_size);
num_blocks = num_blocks_row * num_blocks_col;
watermark = zeros(num_blocks, 1);
for k = 1:length(modified_imgs)
% 提取水印信息
for i = 1:num_blocks_row
for j = 1:num_blocks_col
block = modified_imgs{k}((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size);
lsb = mod(block, 2);
watermark((i-1)*num_blocks_col+j) = lsb(1);
end
end
% 检测篡改区域并彩色标注
diff_blocks = find(watermark ~= watermark(1));
diff_blocks_row = floor((diff_blocks-1)/num_blocks_col)+1;
diff_blocks_col = mod(diff_blocks-1, num_blocks_col)+1;
diff_blocks_img = repmat(modified_imgs{k}, [1,1,3]);
for i = 1:length(diff_blocks)
diff_blocks_img((diff_blocks_row(i)-1)*block_size+1:diff_blocks_row(i)*block_size, (diff_blocks_col(i)-1)*block_size+1:diff_blocks_col(i)*block_size, :) = repmat([255, 0, 0], [block_size, block_size, 1]);
end
% 显示篡改图像和恢复图像
figure(2*k); imshow(diff_blocks_img); title(['篡改后的图像 ', num2str(k)]);
figure(2*k+1); imshow(modified_imgs{k}); title(['恢复后的图像 ', num2str(k)]);
end
%% 恢复篡改区域
clear; clc; close all;
% 读取嵌入水印后的图像
img = imread('watermarked_lena.bmp');
figure(1); imshow(img); title('嵌入水印后的图像');
% 计算篡改后的图像
modified_imgs = cell(5,1);
modified_imgs{1} = imnoise(img, 'gaussian', 0, 0.01);
modified_imgs{2} = imnoise(img, 'gaussian', 0, 0.05);
modified_imgs{3} = imnoise(img, 'salt & pepper', 0.01);
modified_imgs{4} = imnoise(img, 'salt & pepper', 0.05);
modified_imgs{5} = imresize(img, 0.5);
% 提取水印信息并检测篡改区域
block_size = 8;
[M, N] = size(img);
num_blocks_row = floor(M/block_size);
num_blocks_col = floor(N/block_size);
num_blocks = num_blocks_row * num_blocks_col;
watermark = zeros(num_blocks, 1);
for k = 1:length(modified_imgs)
% 提取水印信息
for i = 1:num_blocks_row
for j = 1:num_blocks_col
block = modified_imgs{k}((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size);
lsb = mod(block, 2);
watermark((i-1)*num_blocks_col+j) = lsb(1);
end
end
% 检测篡改区域并恢复内容
diff_blocks = find(watermark ~= watermark(1));
if ~isempty(diff_blocks)
% 定位篡改区域
diff_blocks_row = floor((diff_blocks-1)/num_blocks_col)+1;
diff_blocks_col = mod(diff_blocks-1, num_blocks_col)+1;
% 提取恢复水印信息
recovered_watermark = zeros(num_blocks, 1);
for i = 1:num_blocks_row
for j = 1:num_blocks_col
block = img((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size);
lsb = mod(block, 2);
recovered_watermark((i-1)*num_blocks_col+j) = lsb(1);
end
end
% 利用恢复水印信息恢复篡改区域
recovered_blocks = zeros(block_size, block_size, length(diff_blocks));
for i = 1:length(diff_blocks)
block_row = diff_blocks_row(i);
block_col = diff_blocks_col(i);
block_idx = diff_blocks(i);
recovered_block = zeros(block_size);
for k = 1:8
for l = 1:8
if k == 1 && l == 1
continue;
end
block = modified_imgs{k}((block_row-1)*block_size+1:block_row*block_size, (block_col-1)*block_size+1:block_col*block_size);
recovered_block(k,l) = block(k,l) - mod(block(k,l), 2) + recovered_watermark(block_idx);
end
end
recovered_blocks(:,:,i) = recovered_block;
end
% 合并恢复后的图像块为图像
recovered_img = img;
for i = 1:length(diff_blocks)
block_row = diff_blocks_row(i);
block_col = diff_blocks_col(i);
recovered_img((block_row-1)*block_size+1:block_row*block_size, (block_col-1)*block_size+1:block_col*block_size) = recovered_blocks(:,:,i);
end
% 显示篡改图像和恢复图像
diff_blocks_img = repmat(modified_imgs{k}, [1,1,3]);
for i = 1:length(diff_blocks)
diff_blocks_img((diff_blocks_row(i)-1)*block_size+1:diff_blocks_row(i)*block_size, (diff_blocks_col(i)-1)*block_size+1:diff_blocks_col(i)*block_size, :) = repmat([255, 0, 0], [block_size, block_size, 1]);
end
figure(2*k); imshow(diff_blocks_img); title(['篡改后的图像 ', num2str(k)]);
figure(2*k+1); imshow(recovered_img); title(['恢复后的图像 ', num2str(k)]);
end
end
使用方法:
- 将代码保存为“.m”文件。
- 将lena.bmp图片文件放置在与代码文件同一目录下。
- 运行代码。
输出:
代码将生成以下输出:
- 原始图像
- 嵌入水印后的图像
- 篡改后的图像(共5张,对应5种不同程度的篡改)
- 恢复后的图像(共5张,对应5种不同程度的篡改)
注意:
- 该代码仅供学习参考,实际应用中可能需要根据具体需求进行调整。
- 由于压缩感知算法的局限性,恢复后的图像质量可能无法完全达到原始图像的水平。
原文地址: https://www.cveoy.top/t/topic/oJsp 著作权归作者所有。请勿转载和采集!