[英]Image histogram implementation with Matlab
我正在試圖實現(我知道有一個實現它的自定義函數)Matlab中的灰度圖像直方圖,到目前為止我已經嘗試過:
function h = histogram_matlab(imageSource)
openImage = rgb2gray(imread(imageSource));
[rows,cols] = size(openImage);
histogram_values = [0:255];
for i = 1:rows
for j = 1:cols
p = openImage(i,j);
histogram_values(p) = histogram_values(p) + 1;
end
end
histogram(histogram_values)
但是當我調用該函數時,例如: histogram_matlab('Harris.png')
我得到一些圖形:
這顯然不是我所期望的,x軸應該從0到255,y軸從0到任何最大值都存儲在histogram_values
。
我需要獲得類似imhist
提供的東西:
我該如何設置? 我做得不好嗎?
我已將我的代碼更改為@rayryeng建議的改進和更正:
function h = histogram_matlab(imageSource)
openImage = rgb2gray(imread(imageSource));
[rows,cols] = size(openImage);
histogram_values = zeros(256,1)
for i = 1:rows
for j = 1:cols
p = double(openImage(i,j)) +1;
histogram_values(p) = histogram_values(p) + 1;
end
end
histogram(histogram_values, 0:255)
但直方圖不是預期的:
這里很明顯,y軸上存在一些問題或錯誤,因為它肯定會達到2以上。
在計算直方圖方面,雖然存在輕微誤差,但每個強度的頻率計算是正確的......稍后會有更多。 另外,我個人會避免在這里使用循環。 請參閱本文末尾的小記。
然而,您的代碼有三個問題:
histogram_values
應包含您的直方圖,但您正在通過0:255
的向量初始化直方圖。 每個強度值應以0的計數開始 ,因此您實際需要這樣做:
histogram_values = zeros(256,1);
for
循環中的輕微錯誤 您的強度范圍從0到255,但MATLAB開始索引為1.如果您的強度為0,則會出現越界誤差。 因此,正確的做法是獲取p
並將其添加為1,以便開始在1開始索引。但是,我需要指出的一個復雜性是,如果你有一個uint8
精度圖像,添加1到一個強度為255將簡單地將值飽和到255.它不會達到256 ....所以你也應該謹慎地轉換為double
以確保達到256。
因此:
histogram_values = zeros(256,1);
for i = 1:rows
for j = 1:cols
p = double(openImage(i,j)) + 1;
histogram_values(p) = histogram_values(p) + 1;
end
end
histogram
您應該覆蓋histogram
的行為並包括邊。 基本上,這樣做:
histogram(histogram_values, 0:255);
第二個向量指定我們應該在x
軸上放置條形的位置。
您可以自己完全實現直方圖計算,而無需任何for
循環。 你可以用組合試試這個bsxfun
, permute
, reshape
和兩個sum
調用:
mat = bsxfun(@eq, permute(0:255, [1 3 2]), im);
h = reshape(sum(sum(mat, 2), 1), 256, 1);
如果您想更詳細地解釋這段代碼的工作原理,請參閱kkuilla和我之間的對話: http ://chat.stackoverflow.com/rooms/81987/conversation/explanation-of-computing-an- 圖像直方圖,矢量
但是,它的要點如下。
第一行代碼創建一個1列的3D矢量,范圍從0到255,通過permute
,然后使用帶有eq
(等於)函數的bsxfun
,我們使用廣播,這樣我們得到一個3D矩陣,其中每個切片的大小相同作為灰度圖像,給我們的位置等於感興趣的強度。 具體來說,第一個切片告訴你元素在哪里等於0,第二個切片告訴你哪個元素等於1,直到最后一個切片告訴你元素等於255的位置。
對於第二行代碼,一旦我們計算了這個3D矩陣,我們計算兩個總和 - 首先獨立地對每一行求和,然后對該中間結果的每一列求和。 然后我們得到每個切片的總和,它告訴我們每個強度有多少個值。 因此,這是一個3D矢量,因此我們將其reshape
為單個1D矢量以完成計算。
為了顯示直方圖,我會使用帶有histc
標志的bar
。 如果我們使用cameraman.tif
圖像,這是一個可重現的例子:
%// Read in grayscale image
openImage = imread('cameraman.tif');
[rows,cols] = size(openImage);
%// Your code corrected
histogram_values = zeros(256,1);
for i = 1:rows
for j = 1:cols
p = double(openImage(i,j)) + 1;
histogram_values(p) = histogram_values(p) + 1;
end
end
%// Show histogram
bar(0:255, histogram_values, 'histc');
我們得到這個:
您的代碼看起來正確。 問題在於調用直方圖。 您需要在直方圖調用中提供二進制數,否則將自動計算它們。
嘗試這個簡單的修改,調用詞干來獲得正確的情節,而不是依靠直方圖
function h = histogram_matlab(imageSource)
openImage = rgb2gray(imread(imageSource));
[rows,cols] = size(openImage);
histogram_values = [0:255];
for i = 1:rows
for j = 1:cols
p = openImage(i,j);
histogram_values(p) = histogram_values(p) + 1;
end
end
stem(histogram_values); axis tight;
編輯:經過一些代碼檢查后,你有0/1的錯誤。 如果您的像素值為零,則histogram_value(p)
將為您提供索引錯誤
試試這個。 這個簡單的案例不需要矢量化:
function hv = histogram_matlab_vec(I)
assert(isa(I,'uint8')); % for now we assume uint8 with range [0, 255]
hv = zeros(1,256);
for i = 1 : numel(I)
p = I(i);
hv(p + 1) = hv(p + 1) + 1;
end
stem(hv); axis tight;
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.