(matlab)psnr显示负数,要怎么修改?

代码如下

clc;
clear;
% 加载图像
img = imread('lin.bmp');
% 将图像转换为灰度图像
gray_img = rgb2gray(img);
%将图像类型转换为double类型
gray_img=im2double(gray_img);
% 显示原始图像
subplot(2,3,1);
imshow(gray_img);
title('原始图像');

% 设置水印
watermark = 'Hello World';
% 将水印转换为二进制序列
watermark_bin = dec2bin(watermark, 8);
watermark_bin = watermark_bin(:)';
% 将二进制序列转换为数字序列
watermark_num = str2num(watermark_bin);

% 进行小波变换
[cA,cH,cV,cD] = dwt2(gray_img,'haar');
% 提取水印嵌入位置
embed_pos = 1:4:length(cA(:));
% 将水印嵌入到小波系数中
cA(embed_pos) = cA(embed_pos) + watermark_num;
% 进行逆小波变换
watermarked_img = idwt2(cA,cH,cV,cD,'haar');
% 显示加水印后的图像
subplot(2,3,2);
imshow(uint8(watermarked_img));
title('加水印后的图像');

% 计算PSNR和NC值
[peaksnr, snr] = psnr(watermarked_img, gray_img);

fprintf('PSNR值为:%f\n', peaksnr);


% 提取水印
[cA,cH,cV,cD] = dwt2(watermarked_img,'haar');
% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);
% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);
% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);
% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));
% 显示相关性曲线
subplot(2,3,3);
plot(abs(corr));
title('相关性曲线');

% 添加噪声攻击
noisy_img = imnoise(watermarked_img, 'salt & pepper', 0.05);
% 显示添加噪声后的图像
subplot(2,3,4);
imshow(noisy_img);
title('添加噪声后的图像');

% 提取水印
[cA,cH,cV,cD] = dwt2(noisy_img,'haar');
% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);
% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);
% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);
% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));
% 显示相关性曲线
subplot(2,3,5);
plot(abs(corr));
title('添加噪声后的相关性曲线');

% 添加压缩攻击
imwrite(watermarked_img, 'watermarked_img.jpg', 'jpg', 'Quality', 50);
compressed_img = imread('watermarked_img.jpg');
% 显示压缩后的图像
subplot(2,3,6);
imshow(compressed_img);
title('压缩后的图像');

% 提取水印
[cA,cH,cV,cD] = dwt2(compressed_img,'haar');
% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);
% 对提取的水印进行FFT变换
fft_extracted

有跳出结果,但psnr为负数,要怎么解决。

img

PSNR显示负数的原因是因为峰值信噪比(PSNR)公式是基于原始图像和处理后的图像之间的差异。如果处理后的图像比原始图像的值高,则差异将为负,导致PSNR值为负。解决此问题的一种方法是确保处理后的图像具有与原始图像相同的值范围。您可以尝试将处理后的图像的像素值归一化为0到1之间的值。



clc;
clear;

% 加载图像
img = imread('lin.bmp');

% 将图像转换为灰度图像
gray_img = rgb2gray(img);

%将图像类型转换为double类型
gray_img=im2double(gray_img);

% 显示原始图像
subplot(2,3,1);
imshow(gray_img);
title('原始图像');

% 设置水印
watermark = 'Hello World';

% 将水印转换为二进制序列
watermark_bin = dec2bin(watermark, 8);
watermark_bin = watermark_bin(:)';

% 将二进制序列转换为数字序列
watermark_num = str2num(watermark_bin);

% 进行小波变换
[cA,cH,cV,cD] = dwt2(gray_img,'haar');

% 提取水印嵌入位置
embed_pos = 1:4:length(cA(:));

% 将水印嵌入到小波系数中
cA(embed_pos) = cA(embed_pos) + watermark_num;

% 进行逆小波变换
watermarked_img = idwt2(cA,cH,cV,cD,'haar');

% 显示加水印后的图像
subplot(2,3,2);
imshow(watermarked_img,[]);
title('加水印后的图像');

% 计算PSNR和NC值
[peaksnr, snr] = psnr(watermarked_img, gray_img);

fprintf('PSNR值为:%f\n', peaksnr);

% 提取水印
[cA,cH,cV,cD] = dwt2(watermarked_img,'haar');

% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);

% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);

% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);

% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));

% 显示相关性曲线
subplot(2,3,3);
plot(abs(corr));
title('相关性曲线');

% 添加噪声攻击
noisy_img = imnoise(watermarked_img, 'salt & pepper', 0.05);

% 显示添加噪声后的图像
subplot(2,3,4);
imshow(noisy_img,[]);
title('添加噪声后的图像');

% 提取水印
[cA,cH,cV,cD] = dwt2(noisy_img,'haar');

% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);

% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);

% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);

% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));

% 显示相关性曲线
subplot(2,3,3);
plot(abs(corr));
title('相关性曲线');

% 添加噪声攻击
noisy_img = imnoise(watermarked_img, 'salt & pepper', 0.05);

% 显示添加噪声后的图像
subplot(2,3,4);
imshow(noisy_img,[]);
title('添加噪声后的图像');

% 提取水印
[cA,cH,cV,cD] = dwt2(noisy_img,'haar');

% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);

% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);

% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);

% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));

% 显示相关性曲线
subplot(2,3,5);
plot(abs(corr));
title('添加噪声后的相关性曲线');

% 添加压缩攻击
imwrite(watermarked_img, 'watermarked_img.jpg', 'jpg', 'Quality', 50);
compressed_img = imread('watermarked_img.jpg');

% 显示压缩后的图像
subplot(2,3,6);
imshow(compressed_img,[]);
title('压缩后的图像');

% 提取水印
[cA,cH,cV,cD] = dwt2(compressed_img,'haar');

% 从小波系数中提取嵌入位置的值
extracted_watermark_num = cA(embed_pos);

% 对提取的水印进行FFT变换
fft_extracted_watermark = fft(extracted_watermark_num);

% 对原始水印进行FFT变换
fft_watermark = fft(watermark_num);

% 计算相关性
corr = ifft(fft_extracted_watermark .* conj(fft_watermark));

% 显示相关性曲线
subplot(2,3,6);
plot(abs(corr));
title('压缩后的相关性曲线');
% 显示加水印后的图像
subplot(2,3,2);
imshow(uint8(watermarked_img));
title('加水印后的图像');

%计算图像的最小值
min_val=min(gray_img(:));
max_val=max(gray_img(:));
%对图像进行归一化处理
gray_img_normalized=(gray_img-min_val)/(max_val-min_val)

subplot(2,3,3);
imshow(gray_img_normalized);
title('归一化图像');
% 计算PSNR和NC值
[peaksnr, snr] = psnr(watermarked_img, gray_img);
fprintf('PSNR值为:%f\n', peaksnr);
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:matlab 计算PSNR 代码
  • 除此之外, 这篇博客: MATLAB--数字图像处理 PSNR中的 PSNR 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    概念
    psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准,它具有局限性,一般是用于最大值信号和背景噪音之间的一个工程项目。
    PSNR的单位为dB。值越大,代表失真越少。

    用处
    用来评定图片的图像质量

    PSNR值

    高于40dB:说明图像质量极好(即非常接近原始图像),

    30—40dB:通常表示图像质量是好的(即失真可以察觉但可以接受),

    20—30dB:说明图像质量差;

    低于20dB:图像不可接受

    计算方法
    在这里插入图片描述
    MSE表示当前图像X和参考图像Y的均方误差(MeanSquare Error),H、W分别为图像的高度和宽度;n为每像素的比特数,一般取8,即像素灰阶数为256。

    MATLAB实现

    function PSNR = psnr(f1, f2)
    %计算两幅图像的峰值信噪比
    %f1、f2:两幅图像
    k = 8;
    %k为图像是表示地个像素点所用的二进制位数,即位深。
    fmax = 2.^k - 1;
    a = fmax.^2;
    MSE =(double(im2uint8(f1)) -double( im2uint8(f2))).^2;
    b = mean(mean(MSE));
    PSNR = 10*log10(a/b);
    
  • 以下回答来自chatgpt:

    根据参考资料中的Matlab实现代码中的公式推导出的PSNR值可能为负数,可能是由于MAX值与图像的灰度级不符或MSE计算出的值太大导致的。解决方案可以从以下两个方面入手:

    1.检查MAX值是否正确,是否与图像的灰度级一致(一般为255),可以修改代码中的B值和MAX值,将B设为图像的灰度级,MAX设为2^B-1,一般为255。

    2.检查MSE计算出的值是否过大,可以尝试对图像进行归一化处理,即将像素值除以255,然后再进行PSNR的计算。代码如下:

    img=imread('lena.jpg');
    [h w]=size(img);
    imgn=imresize(img,[floor(h/2) floor(w/2)]);
    imgn=imresize(imgn,[h w]);
    img=double(img)/255; %归一化
    imgn=double(imgn)/255;
    
    B=8;                %编码一个像素用多少二进制位
    MAX=2^B-1;          %图像有多少灰度级
    MES=sum(sum((img-imgn).^2))/(h*w);     %均方差
    PSNR=20*log10(MAX/sqrt(MES));           %峰值信噪比
    

    若以上两种方法都


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^