matlab:在圆形邻居中有效计算局部直方图 [英] matlab: efficient computation of local histograms within circular neighboorhoods

查看:202
本文介绍了matlab:在圆形邻居中有效计算局部直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要在圆形邻域内计算局部直方图的图像。邻域的大小由 radius 给出。虽然下面的代码完成了这项工作,但它的计算成本却很高。我运行探查器,我访问圆形邻域内的像素的方式已经很昂贵了。

I've an image over which I would like to compute a local histogram within a circular neighborhood. The size of the neighborhood is given by a radius. Although the code below does the job, it's computationally expensive. I run the profiler and the way I'm accessing to the pixels within the circular neighborhoods is already expensive.

是否有任何基于矢量化的改进/优化?或者,例如,将邻域存储为列?
我在这个帖子和建议的解决方案中发现了一个类似的问题完全符合下面代码的精神,但是解决方案仍然不适合我的情况。任何想法都非常受欢迎:-)想象一下,目前图像是二进制的,但该方法也应该理想地适用于灰度图像: - )

Is there any sort of improvement/optimization based maybe on vectorization? Or for instance, storing the neighborhoods as columns? I found a similar question in this post and the proposed solution is quite in the spirit of the code below, however the solution is still not appropriate to my case. Any ideas are really welcomed :-) Imagine for the moment, the image is binary, but the method should also ideally work with gray-level images :-)

[rows,cols] = size(img);
hist_img      = zeros(rows, cols, 2);
[XX, YY]      = meshgrid(1:cols, 1:rows);
for rr=1:rows
        for cc=1:cols
            distance      = sqrt( (YY-rr).^2 + (XX-cc).^2  );
            mask_radii = (distance <= radius);
            bwresponses   = img(mask_radii);
            [nelems, ~]   = histc(double(bwresponses),0:255);
            % do some processing over the histogram
            ...
        end
end

编辑1 鉴于收到的反馈意见,我尝试更新解决方案。但是,它还不正确

EDIT 1 Given the received feedback, I tried to update the solution. However, it's not yet correct

radius = sqrt(2.0);
disk   = diskfilter(radius);
fun    = @(x) histc( x(disk>0), min(x(:)):max(x(:)) ); 
output = im2col(im, size(disk), fun);

function disk = diskfilter(radius)
    height  = 2*ceil(radius)+1;
    width   = 2*ceil(radius)+1;
    [XX,YY] = meshgrid(1:width,1:height);
    dist    = sqrt((XX-ceil(width/2)).^2+(YY-ceil(height/2)).^2);
    circfilter = (dist <= radius);
end


推荐答案

你是对的,我不要认为 colfilt 可以用,因为你没有应用过滤器。你必须检查正确性,但这是我尝试使用 im2col 和你的 diskfilter 函数(我确实删除了转换为 double 所以它现在输出逻辑):

You're right, I don't think that colfilt can be used as you're not applying a filter. You'll have to check the correctness, but here's my attempt using im2col and your diskfilter function (I did remove the conversion to double so it now output logicals):

function circhist

% Example data
im = randi(256,20)-1;

% Ranges - I do this globally for the whole image rather than for each neighborhood
mini = min(im(:));
maxi = max(im(:));
edges = linspace(mini,maxi,20);

% Disk filter
radius = sqrt(2.0);
disk = diskfilter(radius); % Returns logical matrix

% Pad array with -1
im_pad = padarray(im, (size(disk)-1)/2, -1);

% Convert sliding neighborhoods to columns
B = im2col(im_pad, size(disk), 'sliding');

% Get elements from each column that correspond to disk (logical indexing)
C = B(disk(:), :);

% Apply histogram across columns to count number of elements
out = histc(C, edges)

% Display output
figure
imagesc(out)
h = colorbar;
ylabel(h,'Counts');
xlabel('Neighborhood #')
ylabel('Bins')
axis xy

function disk = diskfilter(radius)
height  = 2*ceil(radius)+1;
width   = 2*ceil(radius)+1;
[XX,YY] = meshgrid(1:width,1:height);
dist    = sqrt((XX-ceil(width/2)).^2+(YY-ceil(height/2)).^2);
disk = (dist <= radius);

如果你想设定你的范围( edge )基于每个邻域,如果你想构建一个大矩阵(然后那个矩阵的行不会彼此对应),你需要确保向量总是相同的长度。

If you want to set your ranges (edges) based on each neighborhood then you'll need to make sure that the vector is always the same length if you want to build a big matrix (and then the rows of that matrix won't correspond to each other).

您应该注意, fspecial 返回的磁盘形状不像您使用的那样循环。它意味着使用平滑/平均滤波器,因此边缘模糊(消除锯齿)。因此,当您使用〜= 0 时,它将获取更多像素。它坚持你自己的功能,无论如何都要快。

You should note that the shape of the disk returned by fspecial is not as circular as what you were using. It's meant to be used a smoothing/averaging filter so the edges are fuzzy (anti-aliased). Thus when you use ~=0 it will grab more pixels. It'd stick with your own function, which is faster anyways.

这篇关于matlab:在圆形邻居中有效计算局部直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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