Siddhant - 24 days ago 6
Python Question

# Implement angle constraint in the Sobel operator

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.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.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 :

Image Histogram :

Output for some constraints :

0 to 90 degrees

90 to 180 degrees

Thanks.

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.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.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)
``````