# imhistmatch
调整二维图像的直方图以匹配参考图像的直方图
函数库: TyImageProcessing
# 语法
J, = imhistmatch(I,ref)
J, = imhistmatch(I,ref,nbins)
J, = imhistmatch(___;Method=method)
J,hgram = imhistmatch(___)
# 说明
J, = imhistmatch(I,ref) 调整二维灰度或真彩色图像 I 的直方图,使其直方图大致匹配参考图像 ref 的直方图。示例
如果 I 和 ref 都是 RGB 图像,则 imhistmatch 将 I 的每个颜色通道独立匹配到 ref 的相应颜色通道;
如果 I 是 RGB 图像而 ref 是灰度图像,则 imhistmatch 将 I 的每个通道与从 ref 派生的单一直方图进行匹配;
如果 I 是灰度图像,则 ref 也必须是灰度图像。
图像 I 和 ref 不必具有相同的大小。
J, = imhistmatch(I,ref,nbins) 使用 nbins 个均匀间隔的箱子,在给定图像数据类型的适当范围内。返回的图像 J 具有不超过 nbins 个离散级别。
如果图像的数据类型是 Float32 或 Float64,则直方图范围为 [0, 1];
如果图像的数据类型是 UInt8,则直方图范围为 [0, 255];
如果图像的数据类型是 UInt16,则直方图范围为 [0, 65535];
如果图像的数据类型是 Int16,则直方图范围为 [-32768, 32767]。
J, = imhistmatch(___;Method=method) 还指定是否使用均匀或多项式映射技术。示例
J,hgram = imhistmatch(___) 返回用于匹配的参考图像 ref 的直方图 hgram。示例
# 示例
匹配航空图像的直方图
这些航空图像是在不同时间拍摄的,代表了马萨诸塞州康科德同一地形的重叠视图。这个例子演示了输入图像 A 和 Ref 可以具有不同的大小和图像类型。
加载一幅 RGB 图像和一幅参考灰度图像。
using TyImageProcessing
using TyPlot
A = imread("westconcordaerial.png")
Ref = imread("westconcordorthophoto.png")
获取图像 A 的大小。
size(A)
ans =
(394, 369, 3)
获取图像 Ref 的大小。
size(Ref)
ans =
(366, 364)
请注意,图像 A 和 Ref 在大小和类型上是不同的。图像 A 是一个真彩色 RGB 图像,而图像 Ref 是一个灰度图像。两个图像的数据类型都是 uint8。
生成直方图匹配的输出图像。该示例将 A 的每个通道与 Ref 的单一直方图进行匹配。输出图像 B 具有图像 A 的特征 - 它是一个 RGB 图像,大小和数据类型与图像 A 相同。图像 B 中每个 RGB 通道的离散级别数量与从灰度图像 Ref 构建的直方图中的箱子数量相同。在这个例子中,Ref 和 B 的直方图具有默认的箱子数量,即 64。
B, = imhistmatch(A, Ref);
显示 RGB 图像 A、参考图像 Ref 和直方图匹配的 RGB 图像 B。在显示之前,对图像进行了调整大小。
imshow(A)
title("RGB Image with Color Cast")
imshow(Ref)
title("Reference Grayscale Image")
imshow(B)
title("Histogram Matched RGB Image")

使用多项式方法进行直方图匹配图像
读取一幅彩色图像和一幅参考图像。为了演示多项式方法,将参考图像指定为两幅图像中较暗的那幅。
using TyImageProcessing
using TyPlot
I = imread("office_4.jpg");
ref = imread("office_2.jpg");
imshowpair(I, ref, "montage")
title("Input Image (Left) vs Reference Image (Right)");
使用多项式方法调整图像 I 的亮度,使其与参考图像 ref 的直方图匹配。为了进行比较,还使用均匀方法调整图像 I 的亮度。
J, = imhistmatch(I, ref; Method="uniform");
K, = imhistmatch(I, ref; Method="uniform");
imshowpair(J, K, "montage")
title("Histogram-Matched Image Using Uniform Method (Left) vs Uniform Method (Right)");
使用均匀方法进行直方图匹配的图像在天空和道路上引入了伪色彩。而使用多项式方法进行直方图匹配的图像则没有出现这种伪影。
匹配 16 位灰度 MRI 图像的直方图
这个例子展示了如何使用不同数量的箱子进行直方图匹配。
加载一幅通过 MRI 采集的膝关节 16 位 DICOM 图像。
using TyImageProcessing
using TyPlot
using TyMath
using TyBase
pkg_dir = pkgdir(TyImageProcessing)
source_path = pkg_dir * "/resources/knee1_dcm.mat"
K = load(source_path)["A"]; # read in original 16-bit image
LevelsK = ty_unique(K[:]); # determine number of unique code values
println("image K: $(length(LevelsK)) distinct levels");
image K: 448 distinct levels
println("max level = $(maximum(LevelsK))");
max level = 473
println("min level = $(minimum(LevelsK))");
min level = 0
所有 448 个离散值都位于低代码值范围内,这导致图像显得较暗。为了解决这个问题,将图像数据缩放到整个 16 位范围 [0, 65535]。
Kdouble = Float64.(K); # cast uint16 to double
kmult = 65535 / (maximum(maximum(Kdouble[:]))); # full range multiplier
Ref = UInt16.(ty_round.(kmult * Kdouble)); # full range 16-bit reference image
将参考图像 Ref 变暗,以创建一个可以用于直方图匹配操作的图像 A。
#Build concave bow-shaped curve for darkening |Ref|.
ramp = (0:65535) ./ 65535;
ppconcave = spline([0, 0.1, 0.50, 0.72, 0.87, 1], [0, 0.025, 0.25, 0.5, 0.75, 1]);
Ybuf = ppval(ppconcave, ramp);
Lut16bit = UInt16.(ty_round.(65535 * Ybuf));
# Pass image |Ref| through a lookup table (LUT) to darken the image.
A = intlut(Ref, Lut16bit);
查看参考图像 Ref 和变暗后的图像 A。注意它们具有相同数量的离散代码值,但整体亮度不同。
subplot(1, 2, 1)
imshow(Ref)
title("Ref: Reference Image")
subplot(1, 2, 2)
imshow(A)
title("A: Darkened Image");
使用不同数量的箱子生成直方图匹配的输出图像。首先使用默认的箱子数量 64,然后使用图像 A 中存在的值的数量,即 448 个箱子。
B16bit64, = imhistmatch(A[:,:,1],Ref[:,:,1]); # default: 64 bins
N = length(LevelsK); # number of unique 16-bit code values in image A.
B16bitUniq, = imhistmatch(A[:,:,1],Ref[:,:,1],N);
查看这两次直方图匹配操作的结果。
figure()
subplot(1,2,1)
imshow(B16bit64)
title("B16bit64: 64 bins")
subplot(1,2,2)
imshow(Ref)
title("B16bitUniq: $(N) bins")

# 输入参数
I — 输入图像二维 RGB 图像 | 二维灰度图像
要进行变换的输入图像,可以是二维 RGB 或二维灰度图像。imhistmatch 函数期望数据类型为 Float64 和 Float32 的图像值范围在 [0, 1] 之间。如果输入图像的值超出 [0, 1] 范围,可以将值缩放到预期范围。
数据类型: Float32 | Float64 | Int16 | UInt8 | UInt16
ref — 参考图像二维 RGB 图像 | 二维灰度图像
作为参考直方图的参考图像,指定为二维 RGB 或二维灰度图像。参考图像提供了均匀分布的 nbins 直方图,输出图像 J 试图匹配该直方图。
imhistmatch 函数期望数据类型为 Float64 和 Float32 的图像值范围在 [0, 1] 之间。
数据类型: Float32 | Float64 | Int16 | UInt8 | UInt16
nbins — 均匀分布的箱子数量64 (默认) | 正整数
参考直方图中均匀分布的箱子数量,指定为正整数。除了指定图像 ref 中直方图的均匀分布箱子的数量外,nbins 还代表输出图像 J 中存在的离散数据级别的上限。
Method — 映射技术"uniform" (默认) | "polynomial"
用于将 ref 的直方图映射到图像 I 的映射技术,指定为以下值之一:
"uniform" — 使用基于直方图的强度函数和直方图均衡化;
"polynomial" — 从源图像和参考图像的累积分布直方图计算立方 Hermite 多项式映射函数。当参考图像比输入图像暗时,这种多项式方法非常有效。在这种情况下,多项式方法比均匀方法提供更平滑的颜色过渡。
# 输出参数
J — 输出图像二维 RGB 图像 | 二维灰度图像
输出图像,返回为二维 RGB 或二维灰度图像。输出图像来源于图像 I,其直方图与用 nbins 均匀分布的箱子构建的输入图像 ref 的直方图近似匹配。图像 J 的大小和数据类型与输入图像 I 相同。输入参数 nbins 表示图像 J 中包含的离散级别的上限。
数据类型: Float32 | Float64 | Int16 | UInt8 | UInt16
hgram — 从参考图像 ref 导出的直方图计数1×nbins 向量 | 3×nbins 矩阵
从参考图像 ref 导出的直方图计数,指定为向量或矩阵。当 ref 是真实色彩图像时,hgram 是一个 3 行 nbins 列的矩阵,每一行存储 ref 单个颜色通道的直方图。当 ref 是灰度图像时,hgram 是一个 1 行 nbins 列的向量。
数据类型: Float64