我是Matlab的新手,我正在尝试实现代码以执行与histeq
相同的功能,而无需实际使用该函数。在我的代码中,当它不应该改变那么多时,我得到的图像颜色会发生巨大变化。图像中的平均强度(范围在0到255之间)是105.3196。图像是开源花粉粒子。
非常感谢任何帮助。越快越好!由于我的Matlab理解有限,请帮助简化。感谢。
clc;
clear all;
close all;
pollenJpg = imread ('pollen.jpg', 'jpg');
greyscalePollen = rgb2gray (pollenJpg);
histEqPollen = histeq(greyscalePollen);
averagePollen = mean2 (greyscalePollen)
sizeGreyScalePollen = size(greyscalePollen);
rowsGreyScalePollen = sizeGreyScalePollen(1,1);
columnsGreyScalePollen = sizeGreyScalePollen(1,2);
for i = (1:rowsGreyScalePollen)
for j = (1:columnsGreyScalePollen)
if (greyscalePollen(i,j) > averagePollen)
greyscalePollen(i,j) = greyscalePollen(i,j) + (0.1 * averagePollen);
if (greyscalePollen(i,j) > 255)
greyscalePollen(i,j) = 255;
end
elseif (greyscalePollen(i,j) < averagePollen)
greyscalePollen(i,j) = greyscalePollen(i,j) - (0.1 * averagePollen);
if (greyscalePollen(i,j) > 0)
greyscalePollen(i,j) = 0;
end
end
end
end
figure;
imshow (pollenJpg);
title ('Original Image');
figure;
imshow (greyscalePollen);
title ('Attempted Histogram Equalization of Image');
figure;
imshow (histEqPollen);
title ('True Histogram Equalization of Image');
答案 0 :(得分:2)
要实施equalisation algorithm described on the Wikipedia page,请按以下步骤操作:
决定binSize
对灰度值进行分组。 (这是一个可调整的,bin越大,理想情况下的结果越不准确,但我认为如果在真实图像上选择太小则会导致问题。)
然后,计算像素为灰色阴影的概率:
pixelCount = imageWidth * imageHeight
histogram = all zero
for each pixel in image at coordinates i, j
histogram[floor(pixel / 255 / 10) + 1] += 1 / pixelCount // 1-based arrays, not 0-based
// Note a technicality here: you may need to
// write special code to handle pixels of 255,
// because they will fall in their own bin. Or instead use rounding with an offset.
此计算中的直方图被缩放(除以像素数),以使这些值作为概率有意义。你当然可以将除法归结为for循环。
现在你需要计算这个的累积总和:
histogramSum = all zero // length of histogramSum must be one bigger than histogram
for i == 1 .. length(histogram)
histogramSum[i + 1] = histogramSum[i] + histogram[i]
现在你必须反转这个功能,这是一个棘手的部分。最好的方法是不计算显式逆,而是在现场计算,并将其应用于图像。基本思想是在histogramSum中搜索像素值(找到下面最接近的索引),然后在索引和下一个索引之间进行线性插值。
foreach pixel in image at coordinates i, j
hIndex = findIndex(pixel, histogramSum) // You have to write findIndex, it should be simple
equilisationFactor = (pixel - histogramSum[hIndex])/(histogramSum[hIndex + 1] - histogramSum[hIndex]) * binSize
// This above is the linear interpolation step.
// Notice the technicality that you need to handle:
// histogramSum[hIndex + 1] may be out of bounds
equalisedImage[i, j] = pixel * equilisationFactor
编辑:没有钻进数学,我不能100%肯定,但我认为除0错误是可能的。如果一个bin为空,则会发生这些情况,因此连续的总和相等。所以你需要特殊的代码来处理这种情况。您可以做的最好的事情是将因子的值作为hIndex
,hIndex + n
之间的中间值,其中n
是histogramSum[hIndex + n] == histogramSum[hIndex]
的最高值。
一旦你处理了所有技术问题,应该成为它。
上述算法很慢(特别是在findIndex步骤中)。您可以使用特殊的查找数据结构对其进行优化。但只有在工作时才这样做,并且只在必要时才这样做。
关于Matlab代码的另一件事:行和列是反转的。由于算法的对称性,结果是相同的,但它可能会导致其他算法中出现令人费解的错误,如果在调试期间检查像素值,则会非常混乱。在上面的伪代码中,我使用它们和你一样。
答案 1 :(得分:1)
相对较少的(5)行代码可以做到这一点。我在http://commons.wikimedia.org/wiki/File%3ALepismium_lorentzianum_pollen.jpg
找到了一个名为'pollen.jpg'的低对比度文件我在使用您的代码时阅读它,运行以上所有内容,然后执行以下操作:
% find out the index of pixels sorted by intensity:
[gv gi] = sort(greyscalePollen(:));
% create a table of "approximately equal" intensity values:
N = numel(gv);
newVals = repmat(0:255, [ceil(N/256) 1]);
% perform lookup:
% the pixels in sorted order need new values from "equal bins" table:
newImg = zeros(size(greyscalePollen));
newImg(gi) = newVals(1:N);
% if the size of the image doesn't divide into 256, the last bin will have
% slightly fewer pixels in it than the others
当我运行此算法,然后创建四个图像(原始,您的尝试,我的尝试和histeq
)的合成时,您将获得以下内容:
我认为这很有说服力。图像并不完全相同 - 我相信这是因为matlab histeq
例程忽略了值为0的所有像素。因为它是完全矢量化的,所以它也非常快(尽管不如histeq
那么快。在我的图像上约为15倍。
编辑:可能会有一些解释。我用来创建repmat
矩阵的newVals
命令会创建一个如下所示的矩阵:
0 1 2 3 4 ... 255
0 1 2 3 4 ... 255
0 1 2 3 4 ... 255
...
0 1 2 3 4 ... 255
由于matlab以“第一个索引优先”的顺序存储矩阵,如果你用一个索引读取这个矩阵(就像我在行newVals(1:N)
中那样),你首先访问所有零,然后是所有零,等:
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 ...
所以 - 当我按照强度顺序知道像素的索引时(由sort
命令的第二个参数返回,我称之为gi
),然后我可以很容易地分配使用我使用的命令,0
到第一个N/256
像素的值,值1
到下一个N/256
等:
newImg(gi) = newVals(1:N);
我希望这会使代码更容易理解。