直方图与其应有的方式相比差异太大

Histograms too different compared to how they should be

我有一个 black/white 图像 I0 (512 x 512),我必须删除第一个 k 像素并计算结果图像的直方图。

让我解释一下:我必须在不考虑前 k 个像素的情况下构建图像 I0 的直方图。

这是我的代码:

k = 8;

% compute the histogram of the entire image I0
[vecComp, histComp] = histKtoEnd(I0, 0, k);

% compute the histogram of the image I0 without the first k pixel    
[vecWithoutKPixel, histWithoutKPixel] = histKtoEnd(I0, k, k); 

其中:

function [vecWithoutKPixel, hist] = histKtoEnd(image, k, colorDepth)
    % image to row vector
    imageVec = reshape(image.', [], 1);
    l = length(imageVec); 

    % I "delete" the first k pixel
    vecWithoutKPixel = imageVec((k+1) : l-1);
    vecWithoutKPixel(end+1) = imageVec(l); 

    % inizialization
    hist = zeros(1, 2^colorDepth); 

    % create the vector of occurrences
    for i = 0 : (2^colorDepth - 1) 
        grayI = (vecWithoutKPixel == i);
        hist(1, i+1) = sum(grayI(:));
    end
end

要显示两个直方图,请执行以下操作:

subplot(1, 2, 1);
bar(0:2^k-1, histComp, 'r'); 
title('Histogram of the entire image'); 
axis([minColor, maxColor, 0, numberOfPixels]);
subplot(1, 2, 2);
bar(0:2^k-1, histWithoutKPixel, 'r'); 
title('Histogram of the image without the first k pixels'); 
axis([minColor, maxColor, 0, numberOfPixels]);

我得到:

如您所见,直方图非常不同,但应该差别很小,因为差异只有 8 个像素。

我哪里错了?

同样在 warkspace 中,新创建的变量具有这些维度:

vecComp -> 262144 x 1 uint8
histComp -> 1 x 256 double
vecWithoutKPixel -> 65528 x 1 uint8
histWithoutKPixel -> 1 x 256 double

这很奇怪。我应该有:

vecComp -> 262144 x 1
vecWithoutKPixel -> 262136 x 1

有人可以帮助我吗? 谢谢


我正在处理 DICOM 图像和命令 info = dicominfo(filename) get

size = info.FileSize; % 262582; 
colorType = info.ColorType; % grayscale

所以我认为问题不是图像。

如果我在行 vecWithoutKPixel(end+1) = imageVec(l); 上放置一个断点,我得到 imageVec 是 262144 x 1 uint8,并且:

function [vecWithoutKPixel, hist] = histKtoEnd(image, k, colorDepth)
    % image to row vector
    imageVec = reshape(image.', [], 1);
    l = length(imageVec); 

    size(imageVec) % 262144 x 1

    % I "delete" the first k pixel
    vecWithoutKPixel = imageVec((k+1) : l-1);
    vecWithoutKPixel(end+1) = imageVec(l); 

    % inizialization
    hist = zeros(1, 2^colorDepth); 

    % create the vector of occurrences
    for i = 0 : (2^colorDepth - 1) 
        grayI = (vecWithoutKPixel == i);
        hist(1, i+1) = sum(grayI(:));
    end
end

如果我将命令 vecWithoutKPixel = imageVec((k+1) : l-1); vecWithoutKPixel(end+1) = imageVec(l); 更改为 vecWithoutKPixel = imageVec((k+1) : l);,我会得到 vecWithoutKPixel = []

我认为问题在于图像数据最初是 uint8 格式,并在某些时候被转换为 double。因此,行

grayI = (vecWithoutKPixel == i);

in histKtoEnd 可能仅适用于 uint8 数据(因为您将数据与整数进行比较)。

尝试添加行

vecWithoutKPixel = uint8(vecWithoutKPixel);

histKtoEnd函数:

function [vecWithoutKPixel, hist] = histKtoEnd(image, k, colorDepth)
    % image to row vector
    imageVec = reshape(image.', [], 1);
    l = length(imageVec); 

    % I "delete" the first k pixel
    vecWithoutKPixel = imageVec((k+1) : l-1);
    vecWithoutKPixel(end+1) = imageVec(l); 

    % inizialization
    hist = zeros(1, 2^colorDepth); 

    % create the vector of occurrences
    for i = 0 : (2^colorDepth - 1) 
        vecWithoutKPixel = uint8(vecWithoutKPixel);  % Cast to integer
        grayI = (vecWithoutKPixel == i);
        hist(1, i+1) = sum(grayI(:));
    end
end

使用 I0=randi(255,100,100) 创建 'random-image' 然后 运行 您的代码将生成如下图: 我猜这个图看起来和它应该的完全一样,变量的维度也是正确的:

vecComp 10000x1 double
vecWithoutKPixel 9992x1 double

因此我们的问题实际上不是您的代码,而是您的图像。您的图像并不是真正的灰度值,之前其他人已经提到过。但是,不要像@Richard 建议的那样将一些变量转换为 uint8 ,而应该将图像转换为双倍。如果你的图像是 rgb 值使用 I0=double(rgb2gray(I0)); 或者如果它只是 uint8 由于某些其他原因使用 I0=double(I0) 然后将它传递给函数。希望这会有所帮助。