如何不调用histeq函数复现MATLAB中的直方图均衡结果?
如何手动实现与MATLAB histeq完全一致的直方图均衡
我手动实现了直方图均衡,得到的效果还行,但和MATLAB自带的histeq输出不完全一致。希望不调用histeq的前提下,复现它的精确结果。以下是我的代码:
clc, clearvars; x = imread('mri_001.JPG'); [V, B] = hist(double(x(:)), [0:255]); subplot(2, 3, 1); bar(B, V), xlabel('intensity'), ylabel('No. of pixels') y = imread('mri_001.JPG'); normalise = numel(y); [N, C] = hist(double(y(:)), [0:255]); N = N / normalise; subplot(2, 3, 2); bar(C, N), xlabel('intensity'), ylabel('Normalised freq.') z = imread('mri_001.JPG'); normalise = numel(z); [O, D] = hist(double(z(:)), [0:255]); O = O / normalise; M = cumsum(O); subplot(2, 3, 3); bar(D, M), xlabel('cumulative intensity'), ylabel('Normalised freq.') Out = uint8(255 * M(z + 1)); [P, E] = hist(double(Out(:)), [0:255]); subplot(2, 3, 4); bar(E, P), xlabel('manual histeq') k = imread('mri_001.JPG'); L = histeq(k); [Q, F] = hist(double(L(:)), [0:255]); subplot(2, 3, 5); bar(F, Q), xlabel('matlab histeq funct') figure, imshow(Out) % manual histeq figure, imshow(L) % matlab histeq figure, imshow(x) % original
差异原因
你的手动实现和histeq的核心差异在累积分布函数(CDF)的归一化逻辑:
- MATLAB的
histeq会先剔除无像素灰度级带来的累积偏移(减去CDF的最小非零值),再用总像素数减去该最小值做归一化,确保映射范围严格覆盖0-255; - 你的代码直接用归一化直方图的累积值乘以255,没有做偏移修正,同时使用了已被MATLAB弃用的
hist函数,获取的直方图数据精度不如imhist。
修正后的代码
clc, clearvars; % 仅读取一次图像,避免重复IO I = imread('mri_001.JPG'); if size(I,3) == 3 I = rgb2gray(I); % 彩色图自动转灰度,和histeq默认行为一致 end total_pixels = numel(I); % 1. 获取0-255灰度级的精确直方图 [h, gray_levels] = imhist(I, 256); % 2. 计算累积分布函数(CDF) cdf = cumsum(h); % 3. 按照histeq的逻辑归一化CDF:去除无像素灰度级的偏移 min_cdf = cdf(cdf > 0); % 取第一个非零的累积值(跳过无像素的灰度级) min_cdf = min_cdf(1); normalized_cdf = (cdf - min_cdf) / (total_pixels - min_cdf); % 4. 映射灰度级并取整,和histeq内部逻辑一致 normalized_cdf = uint8(round(normalized_cdf * 255)); % 5. 生成均衡后的图像 Out = normalized_cdf(I + 1); % 灰度0对应索引1,匹配MATLAB索引规则 % 对比histeq结果 L = histeq(I); % 可视化验证 figure('Name','直方图对比'); subplot(2,3,1); imhist(I); title('原始直方图'); subplot(2,3,2); imhist(Out); title('手动实现均衡直方图'); subplot(2,3,3); imhist(L); title('histeq均衡直方图'); figure('Name','图像对比'); subplot(1,3,1); imshow(I); title('原始图像'); subplot(1,3,2); imshow(Out); title('手动实现均衡图像'); subplot(1,3,3); imshow(L); title('histeq均衡图像'); % 验证结果完全一致 disp('手动实现与histeq结果是否完全一致:'); disp(all(Out(:) == L(:)));
关键修正点
- 统一图像读取与灰度转换,对齐
histeq的默认处理逻辑; - 用
imhist替代弃用的hist,获取更准确的灰度级直方图; - 修正CDF归一化逻辑,剔除无像素灰度级的累积偏移;
- 对映射后的灰度值做四舍五入取整,匹配
histeq内部的取整操作。
内容的提问来源于stack exchange,提问作者Nathan Lansley
相关产品推荐
相关产品推荐

