how to compute image gradient using Sobel operator

asked 2016-04-21 14:59:49 -0500

nar6du14 gravatar image

Hi everyone, I'm trying to get an orientation map from a fingerprint image but I don't know if the way I compute the gradient in each direction(x and y) is good. That's my python code

Dx = cv2.Sobel(norm_gray_img,cv2.CV_16S,1,0,3)#in x direction
Dy = cv2.Sobel(norm_gray_img,cv2.CV_16S,0,1,3)#in y direction

I also see in some question the use of "cv2.convertScaleAbs" but I don't know why it is used.

all the code are:

def local_vx_vy(Dx,Dy,point,img_size,block_size=(17,17)):
    #point = (x,y) x on col navigation, y on row navigation
    # img_size = (row, col) size of the image row is the nombre
    # of lignes and col the number of column
    x,y = point
    row, col = img_size
    h,w = block_size
    ofi, ofj = w/2,h/2
    Gxy = Gxx = Gyy = 0
    for j in range(-ofj,ofj+1):
    for i in range(-ofi,ofi+1):
        if 0 <= x+i and x+i <= col-1 and 0 <= y+j and y+j <= row-1:
           #print Dx[y+j][x+i], Dy[y+j][x+i], "dx,dy"
           Gxy += (Dx[y+j][x+i])*(Dy[y+j][x+i])
           Gxx += Dx[y+j][x+i]**2
           Gyy += Dy[y+j][x+i]**2
    vx = (2*Gxy)/(w*h)
    vy = (Gxx*Gyy)/(w*h)
    return (vy,vx)

def compute_orientation(norm_gray_img,block_size=(17,17)):
    h,w = block_size
    row,col = norm_gray_img.shape
    ofj, ofi = h/2, w/2
    print norm_gray_img
    Dx = cv2.Sobel(norm_gray_img,cv2.CV_16S,1,0,3)
    Dx = cv2.convertScaleAbs(Dx).astype(np.float)
    Dy = cv2.Sobel(norm_gray_img,cv2.CV_16S,0,1,3)
    Dy = cv2.convertScaleAbs(Dy).astype(np.float)
    Vy = norm_gray_img[0:row-h+1:w, 0:col-h+1:h]
    Vx = Vy.copy()
    angle = Vx.copy()
    r = c = -1
    for j in range(0,row-h+1,h):
        r += 1
        for i in range(0,col-w+1,w):
            c += 1
            Vy[r][c],Vx[r][c] = local_vx_vy(Dx,Dy,(i,j),norm_gray_img.shape,block_size)#
        c = -1
    theta =  0.5*(np.arctan2(Vy,Vx) + M_PI)
    Vx, Vy = cv2.blur(np.cos(theta),(5,5))/25, cv2.blur(np.sin(theta),(5,5))/25
    theta = 0.5*(np.arctan2(Vy,Vx) + M_PI)
    return angle

with the code above and the following plotting function the result is not what I expect

 def plot_point(point, angle, length, ax):
      point - Tuple (x, y)
      angle - Angle you want your end point at in degrees.
      length - Length of the line you want to plot.

      Will plot the line on a 10 x 10 plot.

      # unpack the first point
      x, y = point
      # find the end point
      #print angle
      endx = x + length
      endy = length*math.tan(angle)+y
      ax.plot([x, endx], [y,endy],color='red

image with oriented map') original image

edit retag flag offensive close merge delete


Why is the result bad. It seems that it follows the edges quite closely. You probably want either a

  • Smaller grid and thus more bins
  • Less binning in the orientations possible

Go ahead and perform some tests!

StevenPuttemans gravatar imageStevenPuttemans ( 2016-04-22 06:21:43 -0500 )edit