直方图匹配涉及转换一张图像的直方图,使其看起来像另一张。基本原理是分别计算每个图像的直方图,然后计算它们的离散cumulative distribution functions (CDFs)。让我们将第一个图像的 CDF 表示为,而将第二个图像的 CDF 表示为。因此, 将表示第一张图像的强度x 的 CDF 值。
计算每张图像的 CDF 后,您需要计算一个映射,将第一张图像的一个强度转换为与第二张图像的强度分布一致。为此,对于第一张图像中的每个强度 - 让我们称之为 ,假设是 8 位图像,它将来自 [0,255] - 我们必须在第二张图像中找到强度 (也在[0,255]) 这样:
在某些情况下,我们可能不会完全得到相等,因此您需要做的是找到 和 之间的最小绝对差。换句话说,对于一个映射M,对于的每个条目,我们必须找到一个强度,这样:
您将对所有 256 个值执行此操作,然后我们将生成一个映射。一旦你找到了这个映射,你只需要把这个映射应用到第一个图像上,让它看起来像第二个图像的强度分布。一个粗略的(也许是低效的)算法看起来像这样。设im1 为第一张图片(uint8 类型),im2 为第二张图片(uint8 类型):
M = zeros(256,1,'uint8'); %// Store mapping - Cast to uint8 to respect data type
hist1 = imhist(im1); %// Compute histograms
hist2 = imhist(im2);
cdf1 = cumsum(hist1) / numel(im1); %// Compute CDFs
cdf2 = cumsum(hist2) / numel(im2);
%// Compute the mapping
for idx = 1 : 256
[~,ind] = min(abs(cdf1(idx) - cdf2));
M(idx) = ind-1;
end
%// Now apply the mapping to get first image to make
%// the image look like the distribution of the second image
out = M(double(im1)+1);
out 应该包含匹配的图像,它会转换第一张图像的强度分布以匹配第二张图像的强度分布。请特别注意out 声明。 im1 的强度范围介于 [0,255] 之间,但 MATLAB 对数组的索引从 1 开始。因此,我们需要给im1 的每个值加1,这样我们就可以正确地索引M 来产生我们的输出。但是,im1 的类型为 uint8,如果您尝试超过 255,MATLAB 会使值饱和。因此,为了确保达到 256,我们必须转换为超过 8 位精度的数据类型。我决定使用double,然后当我们将im1 中的每个值都加1 时,我们将跨越1 到256,这样我们就可以正确地索引到M。也不要认为当我找到最小化差异的位置时,我还必须减去 1,因为数据类型跨越 [0,255]。