不同图像堆栈的图像标准化、图像范围和图像缩放

Posted

技术标签:

【中文标题】不同图像堆栈的图像标准化、图像范围和图像缩放【英文标题】:image Normalization, image Range and image Scaling for different stack of images 【发布时间】:2012-06-26 02:15:25 【问题描述】:

我对图像标准化、图像范围和图像缩放感到非常困惑。 我正在使用一种算法(我已在我的Previous Question 中上传了该算法),在应用该算法后,我使用wikipedia 中的这个公式来规范化图像:

使用 MATLAB 中的getrangefromclass(filtImag1i),应用算法前的矩阵范围为 [0 255],应用算法后的矩阵范围为 [0 1]。

问题是我需要找到一个参考来确定归一化公式是否正确?我也有 5 叠图像,每叠包含 600 张图像。我已经为每个堆栈应用了算法,因为算法的结果是每个堆栈有 10 张图像,所以我最终需要对 50 张图像进行分析和比较。我找到了 50 个图像的最大值和最小值,然后将每个图像传递到公式中以对图像进行归一化。

虽然图像的范围是 [0 1] 但图像的最大值是: 最大值 = 3.6714e+004

为什么?不应该是1吗? 这是正常化的正确方法吗? 如何应用缩放?我需要这样做吗?

这是规范化代码:

%%%%%%%%%%%%%%Find Min and Max between the results%%%%%%%%%%%%%%%%%%%%%%% 
pre_max = max(filtImag11(:));
for i=1:10
   new_max = max(filtImag1i(:));
    if (pre_max<new_max)
        pre_max=max(filtImag1i(:));
    end
end
new_max = pre_max;

pre_min = min(filtImag11(:));
for i=1:10
   new_min = min(filtImag1i(:));
    if (pre_min>new_min)
        pre_min = min(filtImag1i(:));
    end
end
new_min = pre_min;

%%%%%%%%%%%%%%normalization %%%%%%%%%%%%%%%%%%%%%%%
 for i=1:10
 temp_imag = filtImag1i(:,:);
 x=isnan(temp_imag);
 temp_imag(x)=0;
 t_max = max(max(temp_imag));
 t_min = min(min(temp_imag));
 temp_imag = (double(temp_imag-t_min)).*((double(new_max)-double(new_min))/double(t_max-t_min))+(double(new_min));
 imag_test2i(:,:) = temp_imag;
 end

编辑 我已经根据建议的答案更改了代码,但结果是黑色图像

%找到它们之间的最大值和最小值 pre_max = max(sTStack1(:)); 对于 i=1:40 newMax = max(sTStacki(:)); 如果(pre_max

pre_min = min(sTStack1(:)); 对于 i=1:40 newMin = min(sTStacki(:)); 如果(pre_min>newMin) pre_min = min(sTStacki(:)); 结尾 结尾 t_min = pre_min;

%%%%%%%%%%%%%%%%%%%%%% 标准化图像:%%%%%%%%%%%%%%%%%%% %%%%%%%%

对于 i=1:40 NTstacki = (sTStacki - t_min)/(t_max-t_min); 结束

对于 i=10:10:40 图,imshow(NTstacki); 彩条 彩色图喷射 结束

【问题讨论】:

你的代码在哪里?别人怎么能不看你的所作所为就回答你的问题? @EitanT 我已经在stackoverfow的上一个链接中上传了它:***.com/questions/10863734/… @user261002 看起来您没有在规范化代码中使用 pre_max 或 pre_min 。这是故意的吗? 【参考方案1】:

我通常将图像处理工具箱中的mat2gray 用于这些目的:mat2gray。我应用了与您在上面提到的完全相同的线性插值。在内部它调用imlincomb。

您所指的问题让我相信您以某种方式错误地执行了上述等式。

【讨论】:

【参考方案2】:

您提供的 Wikipedia sn-p 是正确的,可用于使用以下 MATLAB 代码对图像进行归一化:

%% Create an Example Image:
rand('seed', 1982);
n = 16;
myImg= rand(n,n)*.2 + .5;

%% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

一些图像的问题在于,尽管它们只占据了一小部分可能的值。如果您的值可以介于 0 和 1 之间,则黑色为 0,白色为 1。但是,如果图像中最暗的点是 0.5,最亮的点是 0.7,那么它可能看起来会褪色到您的处理或用户何时被可视化(请注意,MATLAB 的 imagesc 出于这个原因会在显示之前自动对图像进行规范化)。

如果您使用 hist(myImg(:)) 查看图像的直方图,您可以了解图像实际使用的允许值的必要性。在标准化图像中,最小值为 0,最大值为 1(或您使用的任何范围)。

实现这个公式的一个常见错误是没有正确放置括号,在缩放之前没有减去图像的最小值,或者没有添加回“newMin”。

您可以在以下代码和图像中一起查看所有内容。请注意原始图像 (1) 仅使用了一小部分空间 (2),因此当我们不让 imagesc 自动缩放 clim 参数时,它看起来已经褪色。然而,一旦我们对 (3) 进行归一化,图像就会同时具有非常暗和非常亮的值,并且直方图从 0 一直延伸到 1 (4)。虽然尚不清楚您的代码在做什么或没有做什么,但将其与此示例进行比较应该可以解决您的问题。

%% Create an Example Image:
rand('seed', 1982);
n = 16;
myImg= rand(n,n)*.2 + .5;

%% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

%% Display the Image:
figure(42);
clf;

% Display the original:
subplot(2,2,1);
imagesc(myImg);
set(gca, 'clim', [0,1]);;
title('(1) Original Image');

% Display the hist of the original:
subplot(2,2,3);
hist(myImg(:))
xlim([0,1]);
title('(2) Histogram Of Original Image');

% Display the normalized image:
subplot(2,2,2);
imagesc(myImgNorm);
title('(3) Normalized Image');

% Display the hist of the normalized image:
subplot(2,2,4);
hist(myImgNorm(:))
title('(4) Histogram of Normalized Image');
xlim([0,1]);

colormap gray

编辑:

此外,关于 getrangefromclass(...) 将如何解决您的问题,需要注意一些要点。此函数返回“基于其类的图像的默认显示范围”——即,它返回 MATLAB 认为该数据类型表示图片的合理值范围。对于 uint8 数据,这是 [0, 255]。对于 int16,这是 [-32768, 32767]。对于您的情况,双精度,范围是 [0, 1] 不是因为这是最小值和最大值,而是因为这是常规的,双精度数据类型具有特殊的表示形式,使该范围非常合理。 请注意,范围与您的数据实际上是什么无关。如果您的数据小于或大于最小值,则最大值将与 MATLAB 认为适合图片的数据完全不同。在双重或单一的情况下,您的价值可能会大得多。要将值标准化到 [0, 1] 之间,我们可以使用我们一直在讨论的代码。

在这种情况下,我们会创建一个具有大正负值的随机图像,但我们会将它们全部缩放到 0 和 1 之间。也就是说,我们将最暗的颜色设为 0,将亮的颜色设为 1——而在此之前,最小的是负千位,最大的是正千位。但是,请注意当 x 轴值更改为 0,1 时,直方图形状如何保持不变。这应该说明为什么 MATLAB 范围是 [0,1] 但您的最小值/最大值不同——这很好,您的规范化代码将修复零和一之间的所有内容。

randn('seed', 1982);
myImg = randn(n,n)*1000;
% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

% Display the Image:
figure(42);
clf;

% Display the original:
subplot(2,2,1);
imagesc(myImg);
% set(gca, 'clim', [0,1]);;
title('(1) Original Image');
colorbar
% Display the hist of the original:
subplot(2,2,3);
hist(myImg(:))
title('(2) Histogram Of Original Image');
axis tight;

% Display the normalized image:
subplot(2,2,2);
imagesc(myImgNorm);
title('(3) Normalized Image');
colorbar

% Display the hist of the normalized image:
subplot(2,2,4);
hist(myImgNorm(:))
title('(4) Histogram of Normalized Image');
axis tight;

colormap gray

【讨论】:

感谢您的回复和解释,我假设上面的代码仅用于对一张图像进行归一化,但我有 50 张图像,我想确保对所有图像进行归一化。你有什么建议吗?我现在要上传我的代码,请看一下,谢谢 @user261002 您的代码似乎没有错误。我在答案的末尾添加了一些文本来解决 getrangefromclass 返回的内容。在这些范围之外有一个最大值或最小值是可以的,并且规范化会将它们放回这些范围内。 @user261002 你能澄清一下你所说的“在他们之中”是什么意思吗?如果您希望从整个堆栈的最小值和最大值进行标准化,那么我建议您使用示例代码的 pre_min 和 pre_max 而不是 t_min 和 t_max。 exaclty 我想从整个堆栈的最小值和最大值对它们进行标准化,这就是为什么我将它们放入循环中以在 pre_min 和 pre_max 的帮助下找到最小值和最大值。我不知道你是什么意思为什么要使用 pre_min 和 pre_max 而不是 t_min 和 t_max @user261002 如果您看到黑框,则可能是您的堆栈中的一个图像与所有其他图像相比具有较大的值。这可以使所有其他归一化强制“小”值进入接近零的非常小的范围并且看起来是黑色的。如果是这样,您应该在标准化后在堆栈中看到一个“好看”的帧或全白帧。是这样吗?如果是这样,您可以丢弃该单帧并再次运行,或者单独返回对每个图像进行归一化。【参考方案3】:

回答了你之前的问题,我想我理解你的困惑了。

首先,输入图像的类型为uint8(因此范围为[0,255]),由于我们需要对信号进行处理(巴特沃斯滤波),因此需要转换为double数据键入以避免被截断的值。

现在在处理结束时,生成的“图像”类型为double,但具有任意范围(它们代表信号中的平均能量)。现在,如果我们想要显示这些图像,甚至对它们执行图像处理(您试图在原始代码中应用 medfilt2),MATLAB 期望 double 类型的图像在 [0,1] 范围内。

我在代码中使用的公式和您刚刚提供的公式是兼容的,只是我正在规范化到 [0,1] 的范围,因此 newMax = 1newMin = 0 和等式最终简单地为我之前描述过:

 img = ( img - min(img(:)) ) ./ ( max(img(:)) - min(img(:)) );

请记住,您应该单独对每个图像进行归一化,即在公式中为图像本身计算最小值/最大值,而不是从整个图像组中计算。如果你回顾我提出的解决方案,图像存储在一个单元格数组中,并且使用 CELLFUN 完成计算以分别获取每个图像的最小值/最大值:

Tf = cellfun(@(x)reshape((x-min(x))./range(x),sz), Tf, 'Uniform',false);

显然,信号被存储为线性化向量(每个都在一个单元格中),因此我们将每个信号标准化为 [0,1] 范围,然后我们将其重新整形为适当的图像矩阵。

现在,如果您想在那之后返回 uint8 图像,只需调用 im2uint8 即可。

我应该补充一点,我们上面执行的线性变换类型称为最小/最大归一化,但它肯定不是唯一的类型(其他示例请参见 this answer)。人们还可以研究其他对比度增强技术(想想直方图均衡和the like)

【讨论】:

嗨@Amro 谢谢你的回答,但我不明白为什么我需要自己标准化每张图像,我需要比较和分析我的数据,所以我需要我的主管说我有将它们标准化,然后我不会丢失任何数据并且数据将具有可比性

以上是关于不同图像堆栈的图像标准化、图像范围和图像缩放的主要内容,如果未能解决你的问题,请参考以下文章

使用引导程序缩放图像

UIView 背景图像在设备旋转时不缩放

OpenCV Python 系列教程4 - OpenCV 图像处理(上)

在放大和缩小时在imageview上移动对象

iOS - 基于设备的不同图像或缩放相同的图像?

使用 Xamarin Forms 缩放 UWP 图像