过滤器同时使用来自两个数组的元素 [英] filter that uses elements from two arrays at the same time

查看:161
本文介绍了过滤器同时使用来自两个数组的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有两个相同大小的数组 - A B



现在,我们需要一个过滤器,对于给定的掩码大小,从 A 中选择元素,但删除掩码的中心元素,并从 B 插入相应的元素。



所以3x3的伪掩码看起来类似于这个:

  AAA 
ABA
AAA

非常简单。我们可以计算A中没有中心元素的元素的平均值,然后将它与B中元素的适当比例组合:b
$ b $ pre $ c> h = ones(3,3);
h(2,2)= 0;
h = h / sum(h(:));
A_ave = filter2(h,A);
C =(8/9)* A_ave +(1/9)* B;

但是,如何为中值过滤器( medfilt2 或甚至更好 ordfilt2 )

解决方案

解决这个问题是找到一种方法来结合来自A和B的信息,以便过滤本身变得简单。



我想到的第一件事是连接A和B沿着第三维,并通过一个滤波器的面具,将采取A片8个元素和B片的中心元素。这是,不幸的是,不支持的Matlab。

虽然nlfilter只适用于二维图像,它允许您指定任何功能的过滤。因此,你可以创建一个功能,以某种方式能够查找A和B的正确值。因此,我来​​到我的第一个解决方案。

创建一个新的数组C,它包含每个元素的索引,即第一个元素为1,第二个元素为2,等等。运行nlfilter,它需要一个3x3滑动窗口,并将窗口内的C值传递给过滤函数ffn。 ffn是一个匿名函数,它调用crazyFilter,并且已经被初始化,以便A和B在每次调用时都被传递。 CrazyFunction从C的滑动窗口中获取这些值,这些值只是指向A和B的索引,并从A和B中收集这些值。

第二种解决方案除了不是移动滑动窗口,而是创建一个新的数组,该数组在每一列中都有滑动窗口的内容在每个可能的位置。在重叠的窗口中,列数组比原始数组大。再次,您只需要使用列数组C的值(它们是指向A和B的索引)来查找相关位置处的A和B的值。
$ b $如果你有足够的内存,im2col和col2im可以加快处理速度

  %#define A,B 
A = randn(100);
B = rand(100);

%#pad A,B - 您可能想要考虑如何填充
Ap = padarray(A,[1,1]);
Bp = padarray(B,[1,1]);

#%其中 - 更灵活的方法
%#创建一个具有索引而不是值的伪图像
C = zeros(size(Ap));
C(:) = 1:numel(Ap);
%#转换为'列图像',其中每列表示一个块
C = im2col(C,[3,3]);
%#从A
data = Ap(C);
%#用B
data(5,:) = Bp(C(5,:))中的值替换中心。

%#或 - 更有效的方法
%#重塑直接进入窗口并填写B
data = im2col(Ap,[3,3]);
data(5,:) = B(:);

中位数和重塑
out =重塑(中位(数据,1),大小(A));

旧版本(使用较少内存,可能需要填充)

 %#define A,B 
A = randn(100);
B = rand(100);

#定义过滤函数
ffun = @(x)crazyFilter(x,A,B);

%#创建一个具有索引而不是值的伪图像
C = zeros(size(A));
C(:) = 1:numel(A);

%#filter
filteredImage = nlfilter(C,[3,3],ffun);



$ b%#过滤函数
函数out = crazyFilter(输入,A,B)
%#CRAZYFILTER的中位数一个由输入定义的3x3掩码,从A中取8个元素,从B

%中取1个数据,从A
data = A(input(:))中读取数据。
%#使用B
data(5)= B(input(5))中的值替换中心元素;

%#return the median
out = median(data);


Let's assume we have two arrays of the same size - A and B.

Now, we need a filter that, for a given mask size, selects elements from A, but removes the central element of the mask, and inserts there corresponding element from B.

So the 3x3 "pseudo mask" will look similar to this:

A A A
A B A
A A A

Doing something like this for averaging filter is quite simple. We can compute the mean value for elements from A without the central element, and then combine it with a proper proportion with elements from B:

h = ones(3,3);
h(2,2) =0; 
h = h/sum(h(:));
A_ave = filter2(h, A);
C = (8/9) * A_ave + (1/9) * B;

But how to do something similar for median filter (medfilt2 or even better for ordfilt2)

解决方案

The way to solve this is to find a way to combine the information from A and B so that the filtering itself becomes easy.

The first thing I thought of was to catenate A and B along the third dimension and to pass with a filter mask that would take 8 elements from the 'A-slice' and the center element from the 'B-slice'. This is, unfortunately, not supported by Matlab.

While nlfilter only works on 2D images, it does allow you to specify any function for filtering. Thus, you could create a function that somehow is able to look up the right values of A and B. Thus I came to my first solution.

You create a new array, C, that contains the element index at each element, i.e. the first element is 1, the second element is 2, etc. Then, you run nlfilter, which takes a 3x3 sliding window and passes the values of C inside the window to the filtering function, ffn. ffn is an anonymous function, that calls crazyFilter, and that has been initialized so that A and B get passed at each call. CrazyFunction takes the values from the sliding window of C, which are nothing but indices into A and B, and collects the values from A and B from them.

The second solution is exactly the same, except that instead of moving a sliding window, you create a new array that, in every column, has the contents of the sliding window at every possible location. With an overlapping window, the column array gets larger than the original array. Again, you then just need to use the values of the column array, C, which are indices into A and B, to look up the values of A and B at the relevant locations.

EDIT If you have enough memory, im2col and col2im can speed up the process a lot

%# define A,B
A = randn(100);
B = rand(100);

%# pad A, B - you may want to think about how you want to pad
Ap = padarray(A,[1,1]);
Bp = padarray(B,[1,1]);

#% EITHER -- the more more flexible way
%# create a pseudo image that has indices instead of values
C = zeros(size(Ap));
C(:) = 1:numel(Ap);
%# convert to 'column image', where each column represents a block
C = im2col(C,[3,3]);
%# read values from A
data = Ap(C);
%# replace centers with values from B
data(5,:) = Bp(C(5,:));

%# OR -- the more efficient way
%# reshape A directly into windows and fill in B
data = im2col(Ap,[3,3]);
data(5,:) = B(:);

% median and reshape
out = reshape(median(data,1),size(A));

Old version (uses less memory, may need padding)

%# define A,B
A = randn(100);
B = rand(100);

%# define the filter function
ffun = @(x)crazyFilter(x,A,B);

%# create a pseudo image that has indices instead of values
C = zeros(size(A));
C(:) = 1:numel(A);

%# filter
filteredImage = nlfilter(C,[3,3],ffun);




%# filter function
function out = crazyFilter(input,A,B)
%#CRAZYFILTER takes the median of a 3x3 mask defined by input, taking 8 elements from A and 1 from B

%# read data from A
data = A(input(:));
%# replace center element with value from B
data(5) = B(input(5));

%# return the median
out = median(data);

这篇关于过滤器同时使用来自两个数组的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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