Question:
实现一个对灰度图做直方图均衡化的函数(不允许直接调用现成的直方图均衡化接口,例如 Matlab 的“histeq”接口)。函数的格式为“equalize_hist(input_img) output_img”,该函数返回一张灰度级分布均匀的灰度图。如有必要,你可以修改该函数的格式。请载入对应你学号的输入图像,并用你实现的程序来完成以下任务:
1. 计算并显示图像的直方图,并把结果粘贴到报告里。注意:你必须用你自己实现的函数来计算直方图,但是允许调用现成的 API 来显示直方图。(例如,你不能调用 Matlab 的“imhist”来计算直方图,但是可以调用“subplot”, “hist”来显示直方图。)
2. 进行直方图均衡化,将均衡化后的结果和相应的直方图粘贴到报告里。
3. 分析直方图均衡化后的结果,字数不能超过一页。
4. 详细描述你是如何实现直方图均衡化操作的,也就是说,针对“equalize_hist”函数进行算法说明,字数不能超过两页。请集中在算法描述方面,不要过多地复制/粘贴代码到报告上。
Answer:
function [new] = equalize_hist(I) if isstr(I) img = imread(I); end [height,width] = size(img); new = zeros(height,width); %% 创建新图像 figure subplot(221) imshow(img)%显示原始图像 axis on title(['原图像']); %统计像素灰度 NumPixel = zeros(1,256);%用长度为256的一维数组统计各灰度值的数目 for i = 1:height for j = 1: width NumPixel(img(i,j) + 1) = NumPixel(img(i,j) + 1) + 1; end end subplot(222) bar(NumPixel)%显示原始图像直方图 axis on title(['原图像直方图']); %计算PDA PDA = zeros(1,256); for i = 1:256 PDA(i) = NumPixel(i) / (height * width * 1.0); end %计算CDA CDA = zeros(1,256); for i = 1:256 if i == 1 CDA(i) = PDA(i); else CDA(i) = CDA(i - 1) + PDA(i); end end %将CDA乘上最大灰度255并且向上取整 CDA = uint8(255 .* CDA + 0.5); %将原图像各个位置灰度值映射到新值 for i = 1:height for j = 1: width new(i,j) = CDA(img(i,j)+1); end end new = uint8(new); subplot(223) imshow(new)%显示均衡化图像 axis on title(['均衡化图像']); NewNumPixel = zeros(1,256); for i = 1:height for j = 1: width NewNumPixel(new(i,j) + 1) = NewNumPixel(new(i,j) + 1) + 1; end end subplot(224) bar(NewNumPixel)%显示均衡化图像直方图 axis on title(['均衡化图像直方图']);
Algorithm description:
根据书本上的直方图均衡化公式
一步步计算出各个变量即可。简单来说就是将原图像任意(x,y)处的灰度值 r 通过公式所述函数映射到均衡化图像相应位置上的灰度值 s。 第一步: 创建长度为 256 的数组,统计原图像各个灰度值的数目; NumPixel = zeros(1,256);%用长度为 256 的一维数组统计各灰度值的数目 for i = 1:height for j = 1: width NumPixel(img(i,j) + 1) = NumPixel(img(i,j) + 1) + 1; end end 第二步: 计算各个灰度值 PDA; PDA = zeros(1,256); for i = 1:256 PDA(i) = NumPixel(i) / (height * width * 1.0); end 第三步: 计算累积分布函数 CDA,并且乘上 255 取整。 CDA = zeros(1,256); for i = 1:256 if i == 1 CDA(i) = PDA(i); else CDA(i) = CDA(i - 1) + PDA(i); end end 第四步: 直接将原图各个位置像素灰度值映射到均衡化图像上即可。 for i = 1:height for j = 1: width new(i,j) = CDA(img(i,j)+1); end end