Ask Your Question
0

Implement angle constraint in the Sobel operator

asked 2016-11-08 08:13:10 -0600

supertramp-sid gravatar image

I have a couple of doubts related to edge detection in this question.

1) The code I have written below tries to show only those edges which obey a certain constraint of magnitude and direction. The opencv function to display image displays only black when I use the numpy methods. In the show_angle function when I implemented it using for loops and that displayed the image using cv2.imshow.

I then checked the ouput using numpy methods and my for loop using np.array_equal which returned True. What might be the reason behind that?

2) I am not able to work the angle constraints, I will post a few images for different angle constraints.

import cv2

import numpy as np

import matplotlib.pyplot as plt

def show_image(name, img, waitkey=0):
    cv2.namedWindow(name, 0)
    cv2.imshow(name, img)
    cv2.waitKey(waitkey)
    cv2.destroyWindow(name)

img = cv2.imread('hex2.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

shape = img.shape

out_x = cv2.Sobel(img, cv2.CV_16S, 1, 0)    # x gradient
out_y = cv2.Sobel(img, cv2.CV_16S, 0, 1)    # y gradient


out_x = cv2.convertScaleAbs(out_x)
out_y = cv2.convertScaleAbs(out_y)

out_weight = cv2.addWeighted(out_x, 0.5, out_y, 0.5,0)  # x and y weighted


def show_angle(out_weight, mag_final, dir_final, min_mag, theta_min, theta_max):
    """
        Return points based on magnitude and angle constraints
    """


    out_img = np.multiply(
        (
            (mag_final > min_mag) &
            (dir_final > theta_min) &
            (dir_final < theta_max)
        ).astype(int),

        out_weight
    )

    return out_img

def mag_dir():
    """
    Calculate gradient magnitude and direction matrix
    """

    mag = np.sqrt(
                np.add
                     (
                    np.square(out_x) , np.square(out_y)
                      )
                 )

    dir = np.arctan2(out_y, out_x)

    dir = np.multiply(dir, 180)

    print np.min(dir)   # 0
    print np.max(dir)   # 282

    plt.hist(dir,8, (0,360))
    plt.show()

    return mag, dir

mag, dir = mag_dir()



out_img = show_angle(out_weight, mag, dir, 0, 90,120)

plt.imshow(out_img, cmap='gray')
plt.show()

Input image :

hexagon image

Image Histogram :

Image histogram for the hexagon.

Output for some constraints :

0 to 90 degrees

0 to 90 degrees

90 to 180 degrees

90 to 180 degrees

Thanks.

edit retag flag offensive close merge delete

Comments

May I suggest the cartToPolar function? It should be significantly faster than your magDir function, and it's been checked for bugs.

I have a suspicion that that will fix the problem.

Tetragramm gravatar imageTetragramm ( 2016-11-08 12:00:06 -0600 )edit

@Tetragramm I was able to resolve the second issue. the mag_dir function is working ok. But still I am not able to display the image using cv2.imshow

supertramp-sid gravatar imagesupertramp-sid ( 2016-11-09 05:43:20 -0600 )edit
1

Try normalize() with the normType as NORM_MINMAX. The alpha and beta should be the extent of the data type's range, so 1 and 0 for CV_32F or CV_64F, and 255 and 0 for CV_8U. Then it should display properly in imshow.

Tetragramm gravatar imageTetragramm ( 2016-11-09 19:14:57 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-11-12 00:32:52 -0600

supertramp-sid gravatar image

Alright so I found out the mistakes.

There were three problems with my code:

1) In the show_angle function the numpy operators should have had greater than equal to and less than or equal to comparison.

2) I did not divide by pi in the formula used to convert rads to degrees.

3) I should have converted the numpy matrix to uint8 type.

The corrected code :

import cv2

import numpy as np

import matplotlib.pyplot as plt

import math

def show_image(name, img, waitkey=0):
    cv2.namedWindow(name, 0)
    cv2.imshow(name, img)
    cv2.waitKey(waitkey)
    cv2.destroyWindow(name)

img = cv2.imread('hex2.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

shape = img.shape

out_x = cv2.Sobel(img, cv2.CV_16S, 1, 0)    # x gradient
out_y = cv2.Sobel(img, cv2.CV_16S, 0, 1)    # y gradient


out_x = cv2.convertScaleAbs(out_x)
out_y = cv2.convertScaleAbs(out_y)

out_weight = cv2.addWeighted(out_x, 0.5, out_y, 0.5,0)  # x and y weighted


def show_angle(out_weight, mag_final, dir_final, min_mag, theta_min, theta_max):
    """
        Return points based on magnitude and angle constraints
    """


    out_img = np.multiply(
        (
            # (mag_final > min_mag) &
            (dir_final >= theta_min) &
            (dir_final <= theta_max)
        ).astype(int),

        out_weight
    ).astype('uint8')

    return out_img

def mag_dir():
    """
    Calculate gradient magnitude and direction matrix
    """

    mag = np.sqrt(
                np.add
                     (
                    np.square(out_x) , np.square(out_y)
                      )
                 )

    dir = np.arctan2(out_y, out_x)

    dir = np.multiply(dir, 180/math.pi)

    print np.min(dir)   # 0
    print np.max(dir)   # 89

    # plt.hist(mag,8)
    # plt.show()

    return mag, dir

mag, dir = mag_dir()


out_final = show_angle(out_weight, mag, dir, 1, 60, 90)
show_image("angle", out_final, 0)
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-11-08 08:13:10 -0600

Seen: 1,798 times

Last updated: Nov 12 '16