views:

58

answers:

4

Hello everyone.

I'm working on my task in computer vision course. One of sub-tasks is gradient direction computation based on image brightness. I've made a matrix bright[width][height] containing brightness values for every pixel of the image. And i have two such functions:

double Image::grad_x(int x,int y){
    if(x==width-1 || x==0) return bright[x][y];
    return bright[x+1][y]-bright[x-1][y];
}
double Image::grad_y(int x,int y){
    if(y==height-1 || y==0) return bright[x][y];
    return bright[x][y+1]-bright[x][y-1];
}

EDIT: border check fixed

I'm working with simple derivative, without using Sobel operator 'cause simple derivative is sufficient for my needs.

The question is, am i doing this gradient computation right and what exactly do i have to do with border pixels(right now function returns value of the pixel itself, im not sure it's accurate)? And, by the way, is there any utility for computation of gradients of the image? I want to be sure my program is performing well.

A: 

How you deal with borders totally depends on the application. Mirroring, extrapolation, adding zeroes, depending on your needs it will do.

Now you take as border the brightness value, I would not do that, it has no meaning. Just act like your image has more pixels on all borders and mirror, extrapolate or zero their value for your derivative calculation.

Why not taking just a Sobel kernel? It is fast and not more coding effort?

Edit: you do not check the borders in x-direction. grad_x(0, 0) will result in a runtime exception.

cpk
My own. I'm trying to implement simplified version of R-HOG descriptor, in my opinion border pixels are not that important. Right now i added for each border pixel calculation of left and right derivative, depending on which border it presents. I 've never worked with computer vision techics, so i'm not sure it wont affect accuracy of descriptor.
Anton
About sobel kernel - it has same border problems, and after i will finish with this border pixels problem i will change my functions to Sobel kernel using.
Anton
Well, imagine a homogeneous 2D image, full with brightness values of 100. Your image will have derivative 0 everywhere, except for on the borders. It will be 100 there. Depending on the application, this is okay, or it isn't.
cpk
What kind of application do you have and what kind of images (resolution, noisy etc.)? That might say something about the best approach.
cpk
Using left and right derivative will give 0 gradient everywhere, i consider it as right. My app is just a simple people detection system, for practice only. I'm given a set of images(256x256 jpeg) containing people on black background and a set of rectangles, bounding people on that pictures(to simplify training). And i'm computing HOG descriptor for each rectangle containing human.
Anton
Well, if a rectangle is never on the border or out of your image, just ignore the borders and do your analysis on a 254x254 cropped image. Because of the rectangles you cannot expect your gradient to be smooth, so extrapolation or mirroring might not be a good solution. Zeroing (making black) might be a good solution for you approach, because it just creates some more background.
cpk
And hey, they are all simple to implement. Give them all a try and see which one hurts the less!
cpk
A: 

Your computation is correct. It is a simple gradient method you're using, but if that's fine for your use there is nothing wrong with that.

The corner cases are a problem because you don't have enough data to calculate a gradient in the same way as the other pixels. One way to deal with them is to simply not calculate the corner cases and live with a slightly smaller image.

If this is not an option you can also extrapolate the missing data. If you assume that the gradient changes smoothly it works like this:

In your x-gradient calculations you may have calculated the derivate A for pixel 1 and B for pixel 2. If you want to extrapolate a value for pixel 0 (the corner case) the value a-(b-a) could be used.

A numerical example:

  pixel1: gradient = 100
  pixel2: gradient = 80

  extrapolate using a-(b-a): 

  pixel0: gradient = 100 - (80-100)) = 120
Nils Pipenbrinck
A: 

So, on one hand you want to keep it simple on the other hand you want your program to perform well. Huh.

I'm actually doing something similar, though, I don't care much about the border. I like to base the coefficients off of cubic B-Splines. If you convolve your discrete 2D signal with a 2D cubic B-Spline, you'll get a very smooth and twice continuously differentiable function. It's possible to compute the exact intensities and derivatives of this function at arbitrary points. Since the cubic B-Spline is not an interpolator the result will be a bit smoothed compared to the original. But that's not a problem for many applications. In fact, it tends to improve things (suppresing noise to some extent) in many situations. If you don't want this smoothing effect, you can get around it (see my reference below).

In one dimension, reconstruction using the cubic B-Spline as reconstruction filter followed by sampling the signal again is equivalent to convolving the signal with

1/6 4/6 1/6

The exact derivative of this is:

1/2 0 -1/2

And the exact second derivative is:

1 -2 1

These coefficients follow from the cubic B-Spline curve and its derivatives. In 2D you can combine this arbitratily. One filter for the x direction and one filter for the y direction. Examples:

"B-Spline reconstruction" (divisor=36)
   1  4  1
   4 16  4
   1  4  1

"B-Spline differentiator in X" (divisor=12)
   1  0 -1
   4  0 -4
   1  0 -1

"B-Spline, 2nd derivative in X, 1st derivative in Y" (divisor=2)
   1 -2  1
   0  0  0
  -1  2 -1

The nice thing about this is, even though the filtered results don't correspond exactly to the original signal but only a slightly smoothed version, they are nontheless consistent with each other. You can get around the smoothing effect by using a simple preprocessing trick that is described here. You'll also But depending on what you actually want to do, this preprocessing might be inappropriate.

I use this to compute quadratic Taylor approximations at arbitrary (sub-pixel) points to find things like saddle points and local extremums.

If you care about the border you need to somehow choose an extrapolation that fits your needs. I typically just repeat the pixel values of the last pixels. It works well for my applications*.

sellibitze
A: 

Utility:

OpenCV with the convolution kernel you used ([1 0 -1]).

Border pixels:

Depends on the application. Here are some nice ways to pad your image.

Jacob