Search code examples
pythonimage-processingcanny-operator

Gradient of edges Python


I have a dataset with two classes of images: Cityscape and Landscape. What I want to do is calculate the gradient(orientation) of the edges of each image and show that images of cityscapes have more vertical/horizontal edges than landscape images.

What I've done is calculated vertical, horizontal, 45 degree and 135 degree edges. I've applied a Canny filter to the images, calculated the x,y gradients and also applied a threshold to the images show it shows edges above that threshold. The result of this thresholding is seen here: Cityscape edges

This is my code for this image manipulation as well as calculating the gradients:

def gradient(image):    

    # Step 1
    img = image
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Step 2
    bi = cv2.bilateralFilter(gray, 15, 75, 75)

    # Step 3
    dst = cv2.Canny(bi, 100, 200)
    #print(np.count_nonzero(dst))  #--> make sure it's not all zeroes

    # Step 4
    #--- create a black image to see where those edges occur ---
    mask = np.zeros_like(gray)

    #--- applying a threshold and turning those pixels above the threshold to white ---           
    mask[dst > 0.1 * dst.max()] = 255

    # Step 5
    img[dst > 0.1 * dst.max()] = [255, 0, 0]   #--- [255, 0, 0] --> Red ---

    Gx = cv2.Sobel(mask,cv2.CV_64F,1,0,ksize=5)
    Gy = cv2.Sobel(mask,cv2.CV_64F,0,1,ksize=5)

    #orientation of the edges
    theta = np.arctan2(Gy, Gx)

    #magnitude
    M = np.sqrt(Gx*Gx + Gy*Gy)

    #Vertical edges: 
    v = abs(Gy)

    #Horizontal edges: 
    h = abs(Gx)

    #45 Degree edges: 
    deg45 = M*abs(np.cos(theta - np.pi/4))

    #135 Degree edges: 
    deg135 = M*abs(np.cos(theta - 3*np.pi/4))

    print('Vertical:')
    #print(v)
    print(np.count_nonzero(v))
    print('Horizontal:')
    #print(h)
    print(np.count_nonzero(h))

What I want is to calculate the v,h,deg45,deg135 for the edges shown as red in the image above (Step 5). If that is not possible, then do that for the image with the white edges (Step 4). Can anyone help?

EDIT: So as to avoid confusion, what I want to do is to get the amount of vertical, horizontal etc edges in a given image, so that I can compare those numbers for cityscapes vs landscape images.


Solution

  • If what you want is the total number of pixels comprising horizontal vs vertical edges, I would suggest defining some threshold for horizontal vs vertical (say 15 degrees). So you can count the number of elements of theta for which abs(theta) < pi/12 (horizontal) or abs(theta) > pi-pi/12 (horizontal) or pi/2 - pi/12 < abs(theta) < pi/2+pi/12 (vertical)

    What you're storing in v and h are the vertical and horizontal components of the gradient at each point and what you need is to compare the values of v and h to determine for each point if the gradient vector should count as horizontal or vertical. Comparing theta is probably the most intuitive way to do this.

    In order to get the number of elements of theta that satisfy a particular condition, I would suggest using a generator expression:

    sum(1 for i in theta if (abs(i)<pi/12) or (abs(i)>pi-pi/12))
    

    would give you the number of horizontal edge pixels for example.