What is actually applying a filter?

Go To StackoverFlow.com

2

I'm trying solve a challenging problem in C++ with the concepts I'm not familiar with.

I'm trying to apply a filter to a matrix. However like I said I'm quite new at this and after some investigation I've found this link where it shows applying a filter is basically a multiplication

However what confuses me that what if my filter is [0,1,0] and I have to apply it to a 5x5 matrix. How would I be able to do that?

GIMP Filtering with kernel

An alternative to first link

EDIT:Second link really confused me. I am pretty much right now trying to decide the "application" process. If I follow the idea of creating a 3x3 matrix with only diagonal [0,1,0] am i going to apply it like in the second link or do I have to apply it to every single cell in matrix. Or if its really going to be a 1-D filter should I,again, apply it to every single cell or leave out the edges and corners?

2012-04-04 00:23
by Ali
The filter [0, 1, 0] is going to be an identify transformation, unless the different values represent colors, as ElKamina suggests, or some other information is missing - sarnold 2012-04-04 00:36
I gave that one as an example, the main filter I would like use is [-1,0,1 - Ali 2012-04-04 00:37


3

I think the thing that's being overlooked is that the multiplication is repeated for every element of the input array using subsets of the input data.

The GIMP example showed how to filter a 5x5 image using a 3x3 filter for a single pixel:

. . . . .                  . . . . .
. - - - .     . . .        . . . . .
. - @ - .  x  . . .   ->   . . @ . . 
. - - - .     . . .        . . . . .
. . . . .                  . . . . .

I've labelled one input pixel with a @ and its neighbors with -. You use the smaller matrix:

- - -     . . .
- @ -  x  . . .  = 3x3 array
- - -     . . .

Sum up the numbers in the resultant 3x3 array, and store that value into the new image, in place of the @ pixel.

To take this to your example, when filtering a 5x5 image using a 3x1 filter:

. . . . .                  . . . . .
. . . . .                  . . . . .
. - @ - .  x  . . .   ->   . . @ . . 
. . . . .                  . . . . .
. . . . .                  . . . . .

You'll use a smaller subset of the input array, to match your kernel;

- @ -  x  . . .  = 1x3 array

Then, again, sum the numbers in the resultant array, and store that value into the new image in place of the @ pixel.

2012-04-04 00:55
by sarnold
That makes great sense. I'll check it out and possible come back with more questions but your post set a really good foundation for me to start thinking. Thanks! : - Ali 2012-04-04 00:57
I'm checking it over again and the challenge requires for the filter to be applied to x axis and y axis respectively. Does this mean that first I should multiply the filter with first 3 numbers in first row then from 2 to 4(inclusive),then 3 to 5 or something else - Ali 2012-04-04 11:22


4

That's a convolution kernel.

The idea is that you replace each pixel with a weighted average of it and its neighbors, where the weight are given by your convolution kernel. The process is explained nicely e.g. here.

I find strange that you have a 1-D convolution kernel (i.e. that would be suitable for a one-dimensional image), when usually for image processing 2-D convolution kernels (which take pixels also from the rows above/below) are used, but it could be that your algorithm needs to work only with pixel from the current row.

2012-04-04 00:55
by Matteo Italia
I can think of two possible uses for one-dimensional kernels: de-interlacing probably works well enough with a 3x1 vector (vertical), and a simple motion blur could probably be done with a 1x3 vector (horizontal) - sarnold 2012-04-04 01:00
You are exactly right that it is a convolution kernel indeed. I just need to figure out if applying the filter process is going to be multiplication of the numbers in matrix with the filter. I just don't know the "applying" part. Like applying means multiply numbers row by row and then column by column, or something else - Ali 2012-04-04 01:00
I've read the article and its indeed amazing. I just have two questions though: 1)Do we apply this process for every single number in the matrix?(including edges and corners) 2)In your opinion what should I do when it comes to edges and corners (would ignoring rest of the kernel cause a lot of trouble? - Ali 2012-04-04 11:51
1) Yes - 2) If a kernel is made that way it's meant to be applied that way... you can try zeroing the rest of the kernel and try if it has a similar effect, but in line of principle you must apply it as it is - Matteo Italia 2012-04-04 14:27
Another question. [0 1 0] filter means a 3x3 matrix with [0 1 0] diagonal and rest as random numbers, or a 1x3 matrix - Ali 2012-04-04 16:40
@Roland: You'll have to clarify that somewhere else; it could be the diagonal (though rest as random numbers isn't going to be the case -- zeros, maybe, but definitely not random numbers) or it could be a 1x3 matrix. The kernels will do different things, so it is important to figure out what specifically you're being asked to do - sarnold 2012-04-04 22:00


2

It's confusing what you are looking for in an answer. If we make the assumption that your filter is stored in a std::vector<double> called filter and that your image is really 2D and has type std::vector< std::vector<double> > called image, then we can do the following to apply the 1-D filter [-1,0,1]:

 std::vector< std::vector<double> > new_image;
 std::vector<double> filter;
 filter.push_back(-1.0); filter.push_back(0.0); filter.push_back(1.0);

 for(int i = 0; i < image.size(); i++){
     for(int j = 0; j < image.at(i).size(); j++){

         new_image.at(i).push_back( filter.at(0)*image.at(i).at(j-1)
                                    + filter.at(1)*image.at(i).at(j)
                                    + filter.at(2)*image.at(i).at(j+1) );

     }
 }

If you want to have a 2-dimensional filter like this one for example

 [0 1 0]
 [1 0 1]
 [0 1 0]

then we assume it is stored as a vector of vectors as well, and basically do the same.

 std::vector< std::vector<double> > new_image;

 for(int i = 0; i < image.size(); i++){
     for(int j = 0; j < image.at(i).size(); j++){

         top_filter_term = filter.at(0).at(0)*image.at(i-1).at(j-1)
                          + filter.at(0).at(1)*image.at(i-1).at(j)
                          + filter.at(0).at(2)*image.at(i-1).at(j+1);

         mid_filter_term = filter.at(1).at(0)*image.at(i).at(j-1)
                          + filter.at(1).at(1)*image.at(i).at(j)
                          + filter.at(1).at(2)*image.at(i).at(j+1);

         bot_filter_term = filter.at(2).at(0)*image.at(i+1).at(j-1)
                          + filter.at(2).at(1)*image.at(i+1).at(j)
                          + filter.at(2).at(2)*image.at(i+1).at(j+1);

         new_image.at(i).push_back(top_filter_term + mid_filter_term + bot_filter_term);

     }
 }

Please note -- I'm not making any effort to do bounds checking for the filter arrays, you really you should only apply this away from the edges of the image, or add code to apply whatever kinds of boundary conditions you want for your filter. I'm also not making any claims about this being optimized. For most purposes, using vectors is a good way to go because they are dynamically resizable and provide enough built-in support to do a lot of useful image manipulations. But for really large-scale processing, you'll want to optimize things like filter operations.

As for your question about filtering a 3D array, there are a couple of things to consider. One, make sure that you really do want to filter the whole array. For many image processing tasks, it is better and more efficient to split all of the color channels into their own 2D arrays, do your processing, and then put them back together. If you do want a true 3D filter, then be sure that your filter actually is 3D, that is, it will be a vector of vectors of vectors. Then you'll use the exact same logic as above, but you'll have an additional layer of terms for the parts of the filter applied to each color channel, or "slice", of the image.

2012-04-04 01:11
by ely


0

I think you are talking about color filter. Technically a 5X5 image is actually a 5X5X3 (A), where the '3' corresponds to 3 basic colors (RGB). Now, create a matrix of 3X3 with diagonal [0,1,0] (T).

Now multiply the two matrices (AXT) to get the new 5X5X3 image matrix.

2012-04-04 00:34
by ElKamina
Sorry for being 'too new' at this but I got a couple of questions. 1)If i create matrix that has diagonal [0,1,0] rest of the numbers won't have a significant impact - Ali 2012-04-04 00:42
2) I really do not know how to multiply 5x5x3 and 3x3. The three-dimension and two-dimension confuses me - Ali 2012-04-04 00:42
>
  • Yes. Basically your image will have only green color shades. 2. Multiply 5 times individual 5X3 and 3X3 matrices.
  • - ElKamina 2012-04-04 01:17
    Ads