如何将两幅图像叠加并得到这两幅图像的SSIM(相似度指数)值?

发布于 2025-01-09 12:56:22 字数 2375 浏览 3 评论 0原文

我有一个干净的图像和一个嘈杂的图像。我创建了一个降噪器并将其应用于嘈杂的图像,这是我的最终输出。现在,为了比较该图像与干净图像的接近程度,我需要使用 PSNR 和 SSIM 对其进行比较,但由于图像的位置不同,我无法进行比较。

现在我得到的 SSIM 为 0.5,这是非常低的,因为两个图像的位置都不正确。如果图像配准正确,那么我猜 SSIM 应该在 0.80+ 左右。但我没能做到这一点。

如何对齐这两个图像以获得良好的 SSIM 值?

我有两张硬币图像,第一张图像(干净),第二张图像(改进了嘈杂的 IMG),用于比较。

干净的图片:

“在此处输入图像描述”"

嘈杂的 Img:

在此处输入图像描述

由于图像位置不同ssim(img1,img2) 给出了错误的输出。我尝试裁剪,但没有成功。 这是我到目前为止所尝试过的:

尝试 1:

function [valPSNR,valSSIM,badpict]=getSSIM(clean_img,img2)
% pad reference image since object is so close to edges
refpict = padarray(mat2gray(clean_img),[20 20],'replicate','both');
% crop test image down to extract the object alone
badpict = imcrop(mat2gray(img2),[2.5 61.5 357 363]);
% maximize normalized cross-correlation to find offset
szb = size(badpict);
c = normxcorr2(badpict,refpict);
[idxy idxx] = find(c == max(c(:)));
osy = idxy-szb(1);
osx = idxx-szb(2);
% crop the reference pict to the ROI
refpict = refpict(osy:idxy-1,osx:idxx-1);
%imshow(imfuse(badpict,refpict,'checkerboard'));
%imagesc(badpict);
valSSIM=ssim(badpict,refpict);
valPSNR=getPSNR(badpict,refpict);
img2=badpict;
clean_img=refpict;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end

尝试 2:

function [valPSNR,valSSIM,badpict]=getSSIM2(clean_img,img2)
% pad reference image since object is so close to edges
bw1 = im2bw(mat2gray(clean_img));
bw2 = imclose(im2bw(mat2gray(img2),0.3),strel('disk',9));
bw2 = bwareafilt(bw2,1);
% make same size
[r,c] = find(bw1);
clean_img = clean_img(min(r):max(r),min(c):max(c));
[r,c] = find(bw2);
img2 = img2(min(r):max(r),min(c):max(c));
img2= imresize(img2, size(clean_img),'bilinear');
valPSNR=getPSNR(mat2gray(clean_img),mat2gray(img2));
valSSIM=ssim(mat2gray(clean_img),mat2gray(img2));
badpict=img2;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end

I have a clean image, and a noisy image. I created a denoiser and applied it to the noisy image, that was my final output. Now to compare how much this image is close to a clean image I need to compare it using PSNR and SSIM, but due to different positions of the image I am unable to compare.

Now I am getting SSIM as 0.5, which is very low, due to the improper placement of both the images. If the images are registered properly, then I guess SSIM should come around 0.80+. But I have not been able to accomplish this.

How can I align these two images to obtain a good SSIM value?

I have two coin images, 1st image (CLEAN), 2nd image (IMPROVED a NOISY IMG), for comparison.

Clean Img:

enter image description here

Noisy Img:

enter image description here

Due to positions of images at different positions ssim(img1,img2) is giving incorrect output. I tried cropping but that did not work.
Here is what I have tried so far:

Attempt 1:

function [valPSNR,valSSIM,badpict]=getSSIM(clean_img,img2)
% pad reference image since object is so close to edges
refpict = padarray(mat2gray(clean_img),[20 20],'replicate','both');
% crop test image down to extract the object alone
badpict = imcrop(mat2gray(img2),[2.5 61.5 357 363]);
% maximize normalized cross-correlation to find offset
szb = size(badpict);
c = normxcorr2(badpict,refpict);
[idxy idxx] = find(c == max(c(:)));
osy = idxy-szb(1);
osx = idxx-szb(2);
% crop the reference pict to the ROI
refpict = refpict(osy:idxy-1,osx:idxx-1);
%imshow(imfuse(badpict,refpict,'checkerboard'));
%imagesc(badpict);
valSSIM=ssim(badpict,refpict);
valPSNR=getPSNR(badpict,refpict);
img2=badpict;
clean_img=refpict;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end

Attempt 2:

function [valPSNR,valSSIM,badpict]=getSSIM2(clean_img,img2)
% pad reference image since object is so close to edges
bw1 = im2bw(mat2gray(clean_img));
bw2 = imclose(im2bw(mat2gray(img2),0.3),strel('disk',9));
bw2 = bwareafilt(bw2,1);
% make same size
[r,c] = find(bw1);
clean_img = clean_img(min(r):max(r),min(c):max(c));
[r,c] = find(bw2);
img2 = img2(min(r):max(r),min(c):max(c));
img2= imresize(img2, size(clean_img),'bilinear');
valPSNR=getPSNR(mat2gray(clean_img),mat2gray(img2));
valSSIM=ssim(mat2gray(clean_img),mat2gray(img2));
badpict=img2;
figure; imshowpair(clean_img,img2);
figure; montage({mat2gray(clean_img),mat2gray(img2)}, 'Size', [1 2], 'BackgroundColor', 'w', 'BorderSize', [2 2]);
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

じее 2025-01-16 12:56:22

正如其他人指出的那样,注册所需的重采样将产生一些非零误差。但是,这里有一些示例代码,将引导您完成注册部分,这是问题的关键。

% SSIM isn't defined on RGB images, convert to grayscale.
ref = rgb2gray(imread('https://i.sstatic.net/tPKEJ.png'));
X = rgb2gray(imread('https://i.sstatic.net/KmU4y.png'));

% The input image data has bright borders at the edges that create
% artifacts in resampling, best to just crop those or maybe there are
% aquisitions that don't have these borders?
X = X(3:end-2,3:end-2);
ref = ref(4:end-3,4:end-3);

figure
montage({X,ref});

tform = imregcorr(X,ref,"translation");

Xreg = imwarp(X,tform,OutputView=imref2d(size(ref)),SmoothEdges=true);

figure
imshowpair(Xreg,ref)

ssim(Xreg,ref)

As others have pointed out, the resampling required by registration will have some non-zero error. But, here is some sample code that will take you through the registration part that is the crux of your question.

% SSIM isn't defined on RGB images, convert to grayscale.
ref = rgb2gray(imread('https://i.sstatic.net/tPKEJ.png'));
X = rgb2gray(imread('https://i.sstatic.net/KmU4y.png'));

% The input image data has bright borders at the edges that create
% artifacts in resampling, best to just crop those or maybe there are
% aquisitions that don't have these borders?
X = X(3:end-2,3:end-2);
ref = ref(4:end-3,4:end-3);

figure
montage({X,ref});

tform = imregcorr(X,ref,"translation");

Xreg = imwarp(X,tform,OutputView=imref2d(size(ref)),SmoothEdges=true);

figure
imshowpair(Xreg,ref)

ssim(Xreg,ref)
眼波传意 2025-01-16 12:56:22

也许你可以参考我的github

我通过 OpenCV 实现了一个模板匹配算法,您可以使用基于 NCC 的模式匹配来查找目标,然后获得一个分数(相似度)。

然后您可以使用这个分数来决定是否干净。

此外,转换c++代码对你来说可能是个问题,但只需在matlab版本中找到所有相应的函数即可。

效果如下(红色块是与黄金样本相比相似度高于阈值0.85的区域):
输入图片这里的描述

整个功能太长,无法在这里发布。
部分功能:

for (int i = 0; i < iSize; i++)
{
    Mat matRotatedSrc, matR = getRotationMatrix2D (ptCenter, vecAngles[i], 1);
    Mat matResult;
    Point ptMaxLoc;
    double dValue, dMaxVal;
    double dRotate = clock ();
    Size sizeBest = GetBestRotationSize (vecMatSrcPyr[iTopLayer].size (), pTemplData->vecPyramid[iTopLayer].size (), vecAngles[i]);
    float fTranslationX = (sizeBest.width - 1) / 2.0f - ptCenter.x;
    float fTranslationY = (sizeBest.height - 1) / 2.0f - ptCenter.y;
    matR.at<double> (0, 2) += fTranslationX;
    matR.at<double> (1, 2) += fTranslationY;
    warpAffine (vecMatSrcPyr[iTopLayer], matRotatedSrc, matR, sizeBest);


    MatchTemplate (matRotatedSrc, pTemplData, matResult, iTopLayer);

    minMaxLoc (matResult, 0, &dMaxVal, 0, &ptMaxLoc);

    vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM)] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dMaxVal, vecAngles[i]);

    for (int j = 0; j < m_iMaxPos + MATCH_CANDIDATE_NUM - 1; j++)
    {
        ptMaxLoc = GetNextMaxLoc (matResult, ptMaxLoc, -1, pTemplData->vecPyramid[iTopLayer].cols, pTemplData->vecPyramid[iTopLayer].rows, dValue, m_dMaxOverlap);
        vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM) + j + 1] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dValue, vecAngles[i]);
    }
}
FilterWithScore (&vecMatchParameter, m_dScore-0.05*iTopLayer);

Maybe you can refer to my github.

I implemented a template matching algorithm by OpenCV which you can use NCC-Based Pattern Matching to find targets, and then get a score (similarity).

You can then use this score to decide if it is clean.

Besides, tranforming c++ code may be an issue for you, but just find the all corresponded function in matlab version.

Here are effects (red blocks are areas with similarity higher than threshold 0.85 in comparison with golden sample):
enter image description here

The whole function is too long to be posted here.
Part of the function:

for (int i = 0; i < iSize; i++)
{
    Mat matRotatedSrc, matR = getRotationMatrix2D (ptCenter, vecAngles[i], 1);
    Mat matResult;
    Point ptMaxLoc;
    double dValue, dMaxVal;
    double dRotate = clock ();
    Size sizeBest = GetBestRotationSize (vecMatSrcPyr[iTopLayer].size (), pTemplData->vecPyramid[iTopLayer].size (), vecAngles[i]);
    float fTranslationX = (sizeBest.width - 1) / 2.0f - ptCenter.x;
    float fTranslationY = (sizeBest.height - 1) / 2.0f - ptCenter.y;
    matR.at<double> (0, 2) += fTranslationX;
    matR.at<double> (1, 2) += fTranslationY;
    warpAffine (vecMatSrcPyr[iTopLayer], matRotatedSrc, matR, sizeBest);


    MatchTemplate (matRotatedSrc, pTemplData, matResult, iTopLayer);

    minMaxLoc (matResult, 0, &dMaxVal, 0, &ptMaxLoc);

    vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM)] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dMaxVal, vecAngles[i]);

    for (int j = 0; j < m_iMaxPos + MATCH_CANDIDATE_NUM - 1; j++)
    {
        ptMaxLoc = GetNextMaxLoc (matResult, ptMaxLoc, -1, pTemplData->vecPyramid[iTopLayer].cols, pTemplData->vecPyramid[iTopLayer].rows, dValue, m_dMaxOverlap);
        vecMatchParameter[i * (m_iMaxPos + MATCH_CANDIDATE_NUM) + j + 1] = s_MatchParameter (Point2f (ptMaxLoc.x - fTranslationX, ptMaxLoc.y - fTranslationY), dValue, vecAngles[i]);
    }
}
FilterWithScore (&vecMatchParameter, m_dScore-0.05*iTopLayer);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文