使用Matlab实现图像直方图 [英] Image histogram implementation with Matlab

查看:211
本文介绍了使用Matlab实现图像直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实施(我知道有一个实现它的自定义功能)Matlab中的灰度图像直方图,到目前为止我已经尝试过:

I'm tyring to implement (I know there's a custom function for achieving it) the grayscale image histogram in Matlab, so far I've tried:

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')

However when I call the function, for example: histogram_matlab('Harris.png')

我获得了一些图如:

这显然不是我的预期,x轴应该从0到255,y轴从0到任何最大值都存储在 histogram_values

which is obviously not what I expect, x axis should go from 0 to 255 and y axis from 0 to whatever max value is stored in histogram_values.

我需要获得类似什么 imhist 优惠:

I need to obtain something like what imhist offers:

我该如何设置?我执行得不好吗?

How should I set it up? Am I doing a bad implementation?

我已将代码更改为改进和更正建议@rayryeng:

I've changed my code to improvements and corrections suggested by @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)

然而直方图不是预期的:

However the histogram plot is not that expected:

这里很明显,y轴上存在一些问题或错误,因为它肯定会超过2个。

Here it's noticeable that there's some issue or error on y axis as it definitely would reach MORE than 2.

推荐答案

在计算直方图方面,虽然存在轻微误差,但每个强度的频率计算是正确的......稍后会详细说明。另外,我个人会避免在这里使用循环。请参阅本文末尾的小注释。

In terms of calculating the histogram, the computation of the frequency per intensity is correct though there is a slight error... more on that later. Also, I would personally avoid using loops here. See my small note at the end of this post.

然而,您的代码存在三个问题:

Nevertheless, there are three problems with your code:

histogram_values 应该包含你的直方图,但你正在初始化直方图通过 0:255 的向量。每个强度值应以0 开始,因此您实际需要这样做:

histogram_values should contain your histogram, yet you are initializing the histogram by a vector of 0:255. Each intensity value should start with a count of 0, and so you actually need to do this:

histogram_values = zeros(256,1);



问题#2 - 中的轻微错误循环



您的强度范围从0到255,但MATLAB开始索引为1.如果您的强度为0,则会出现超出范围的错误。因此,正确的做法是采用 p 并将其添加为1,以便开始索引为1.但是,我需要指出的一个复杂性是,如果你有一个 uint8 精度图像,加上1强度为255只会将值饱和到255.它不会达到256 ....所以它也是谨慎的您投射到 double 之类的东西,以确保达到256。

Problem #2 - Slight error in for loop

Your intensities range from 0 to 255, yet MATLAB starts indexing at 1. If you ever get intensities that are 0, you will get an out-of-bounds error. As such, the proper thing to do is to take p and add it with 1 so that you start indexing at 1. However, one intricacy I need to point out is that if you have a uint8 precision image, adding 1 to an intensity of 255 will simply saturate the value to 255. It won't go to 256.... so it's also prudent that you cast to something like double to ensure that 256 will be reached.

因此:

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



问题#3 - 不致电 histogram right



你应该覆盖 histogram 的行为,包括边缘。基本上,这样做:

Problem #3 - Not calling histogram right

You should override the behaviour of histogram and include the edges. Basically, do this:

histogram(histogram_values, 0:255);

第二个向量指定我们应该在 x -axis。

The second vector specifies where we should place bars on the x-axis.

你可以自己完全实现直方图计算而不需要任何 for 循环。您可以结合使用 bsxfun permute reshape 和两个 总和 来电:

You can totally implement the histogram computation yourself without any for loops. You can try this with a combination of bsxfun, permute, reshape and two sum calls:

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-images-histogram-vectorized

然而,它的要点如下。

第一行代码创建一个3D向量的1列,范围从0到255 置换,然后使用 bsxfun eq (等于)函数,我们使用广播,以便我们得到一个3D矩阵,其中每个切片与灰度图像的大小相同,并为我们提供等于感兴趣强度的位置。具体来说,第一个切片告诉你元素在哪里等于0,第二个切片告诉你哪个元素等于1直到最后一个切片,它告诉你元素等于255的位置。

The first line of code creates a 3D vector of 1 column that ranges from 0 to 255 by permute, and then using bsxfun with the eq (equals) function, we use broadcasting so that we get a 3D matrix where each slice is the same size as the grayscale image and gives us locations that are equal to an intensity of interest. Specifically, the first slice tells you where elements are equal to 0, the second slice tells you where elements are equal to 1 up until the last slice where it tells you where elements are equal to 255.

对于第二行代码,一旦我们计算出这个3D矩阵,我们计算两个总和 - 首先独立地对每一行求和,然后对该中间结果的每一列求和。然后我们得到每个切片的总和,它告诉我们每个强度有多少个值。因此这是一个3D矢量,所以我们重塑这会重新变成一个1D矢量来完成计算。

For the second line of code, once we compute this 3D matrix, we compute two sums - first summing each row independently, then summing each column of this intermediate result. We then get the total sum per slice which tells us how many values there were for each intensity. This is consequently a 3D vector, and so we reshape this back into a single 1D vector to finish the computation.

为了显示直方图,我会使用 bar histc 旗帜。如果我们使用 cameraman.tif 图像,这是一个可重现的例子:

In order to display a histogram, I would use bar with the histc flag. Here's a reproducible example if we use the cameraman.tif image:

%// 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');

我们得到这个:

这篇关于使用Matlab实现图像直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆