Threshold an image for a given range and Sobel kernel

 Clash Royale CLAN TAG#URR8PPP
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
The class defines functions to threshold an image for a given range and Sobel kernel. Each function has similarities, i.e. they share the same following tasks:
- each function converts an image to grayscale
- take the gradient
- rescale to 8 bit
- apply a threshold, and create a binary image result
class GRADIENT_THRESHOLD(object):
 '''
 Define functions to threshold an image for a given range and Sobel kernel
 '''
 def __init__(self, args):
 self.args = args
 def gradient_abs_sobel(self, img, orient='x', sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take the absolute value of the gradient in given orient = 'x' or 'y'
 if orient == 'x':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
 if orient == 'y':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
 # scale to 8-bit (0 - 255) then convert to type = np.uint8
 scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
 # create a mask of 1's where the scaled gradient magnitude
 # is > thresh_min and < thresh_max
 binary_output = np.zeros_like(scaled_sobel)
 # return this mask as your binary_output image
 binary_output[(scaled_sobel >= thresh[0]) & (scaled_sobel <= thresh[1])] = 1
 # return the binary image
 return binary_output 
 def gradient_magnitude(self, img, sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # calculate the gradient magnitude
 gradmag = np.sqrt(sobelx**2 + sobely**2)
 # rescale to 8 bit
 scale_factor = np.max(gradmag)/255 
 gradmag = (gradmag/scale_factor).astype(np.uint8) 
 # create a binary image of ones where threshold is met, zeros otherwise
 binary_output = np.zeros_like(gradmag)
 binary_output[(gradmag >= thresh[0]) & (gradmag <= thresh[1])] = 1
 # return the binary image
 return binary_output
 # Define a function to threshold an image for a given range and Sobel kernel
 def gradient_direction(self, img, sobel_kernel=3, thresh=(0, np.pi/2)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # take the absolute value of the gradient direction
 absgraddir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
 # apply a threshold, and create a binary image result
 binary_output = np.zeros_like(absgraddir)
 binary_output[(absgraddir >= thresh[0]) & (absgraddir <= thresh[1])] = 1
 # return the binary image
 return binary_output
python performance object-oriented image
add a comment |Â
up vote
5
down vote
favorite
The class defines functions to threshold an image for a given range and Sobel kernel. Each function has similarities, i.e. they share the same following tasks:
- each function converts an image to grayscale
- take the gradient
- rescale to 8 bit
- apply a threshold, and create a binary image result
class GRADIENT_THRESHOLD(object):
 '''
 Define functions to threshold an image for a given range and Sobel kernel
 '''
 def __init__(self, args):
 self.args = args
 def gradient_abs_sobel(self, img, orient='x', sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take the absolute value of the gradient in given orient = 'x' or 'y'
 if orient == 'x':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
 if orient == 'y':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
 # scale to 8-bit (0 - 255) then convert to type = np.uint8
 scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
 # create a mask of 1's where the scaled gradient magnitude
 # is > thresh_min and < thresh_max
 binary_output = np.zeros_like(scaled_sobel)
 # return this mask as your binary_output image
 binary_output[(scaled_sobel >= thresh[0]) & (scaled_sobel <= thresh[1])] = 1
 # return the binary image
 return binary_output 
 def gradient_magnitude(self, img, sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # calculate the gradient magnitude
 gradmag = np.sqrt(sobelx**2 + sobely**2)
 # rescale to 8 bit
 scale_factor = np.max(gradmag)/255 
 gradmag = (gradmag/scale_factor).astype(np.uint8) 
 # create a binary image of ones where threshold is met, zeros otherwise
 binary_output = np.zeros_like(gradmag)
 binary_output[(gradmag >= thresh[0]) & (gradmag <= thresh[1])] = 1
 # return the binary image
 return binary_output
 # Define a function to threshold an image for a given range and Sobel kernel
 def gradient_direction(self, img, sobel_kernel=3, thresh=(0, np.pi/2)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # take the absolute value of the gradient direction
 absgraddir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
 # apply a threshold, and create a binary image result
 binary_output = np.zeros_like(absgraddir)
 binary_output[(absgraddir >= thresh[0]) & (absgraddir <= thresh[1])] = 1
 # return the binary image
 return binary_output
python performance object-oriented image
 
 
 2
 
 
 
 
 in- gradient_directionI see no scaling. Is this intentional?
 â Maarten Fabré
 Apr 17 at 15:08
 
 
 
 
 
 
 
 
 
 @MaartenFabré, yes, it is.
 â mo2
 Apr 21 at 21:12
 
 
 
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
The class defines functions to threshold an image for a given range and Sobel kernel. Each function has similarities, i.e. they share the same following tasks:
- each function converts an image to grayscale
- take the gradient
- rescale to 8 bit
- apply a threshold, and create a binary image result
class GRADIENT_THRESHOLD(object):
 '''
 Define functions to threshold an image for a given range and Sobel kernel
 '''
 def __init__(self, args):
 self.args = args
 def gradient_abs_sobel(self, img, orient='x', sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take the absolute value of the gradient in given orient = 'x' or 'y'
 if orient == 'x':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
 if orient == 'y':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
 # scale to 8-bit (0 - 255) then convert to type = np.uint8
 scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
 # create a mask of 1's where the scaled gradient magnitude
 # is > thresh_min and < thresh_max
 binary_output = np.zeros_like(scaled_sobel)
 # return this mask as your binary_output image
 binary_output[(scaled_sobel >= thresh[0]) & (scaled_sobel <= thresh[1])] = 1
 # return the binary image
 return binary_output 
 def gradient_magnitude(self, img, sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # calculate the gradient magnitude
 gradmag = np.sqrt(sobelx**2 + sobely**2)
 # rescale to 8 bit
 scale_factor = np.max(gradmag)/255 
 gradmag = (gradmag/scale_factor).astype(np.uint8) 
 # create a binary image of ones where threshold is met, zeros otherwise
 binary_output = np.zeros_like(gradmag)
 binary_output[(gradmag >= thresh[0]) & (gradmag <= thresh[1])] = 1
 # return the binary image
 return binary_output
 # Define a function to threshold an image for a given range and Sobel kernel
 def gradient_direction(self, img, sobel_kernel=3, thresh=(0, np.pi/2)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # take the absolute value of the gradient direction
 absgraddir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
 # apply a threshold, and create a binary image result
 binary_output = np.zeros_like(absgraddir)
 binary_output[(absgraddir >= thresh[0]) & (absgraddir <= thresh[1])] = 1
 # return the binary image
 return binary_output
python performance object-oriented image
The class defines functions to threshold an image for a given range and Sobel kernel. Each function has similarities, i.e. they share the same following tasks:
- each function converts an image to grayscale
- take the gradient
- rescale to 8 bit
- apply a threshold, and create a binary image result
class GRADIENT_THRESHOLD(object):
 '''
 Define functions to threshold an image for a given range and Sobel kernel
 '''
 def __init__(self, args):
 self.args = args
 def gradient_abs_sobel(self, img, orient='x', sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take the absolute value of the gradient in given orient = 'x' or 'y'
 if orient == 'x':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
 if orient == 'y':
 abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
 # scale to 8-bit (0 - 255) then convert to type = np.uint8
 scaled_sobel = np.uint8(255*abs_sobel/np.max(abs_sobel))
 # create a mask of 1's where the scaled gradient magnitude
 # is > thresh_min and < thresh_max
 binary_output = np.zeros_like(scaled_sobel)
 # return this mask as your binary_output image
 binary_output[(scaled_sobel >= thresh[0]) & (scaled_sobel <= thresh[1])] = 1
 # return the binary image
 return binary_output 
 def gradient_magnitude(self, img, sobel_kernel=3, thresh=(0, 255)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # calculate the gradient magnitude
 gradmag = np.sqrt(sobelx**2 + sobely**2)
 # rescale to 8 bit
 scale_factor = np.max(gradmag)/255 
 gradmag = (gradmag/scale_factor).astype(np.uint8) 
 # create a binary image of ones where threshold is met, zeros otherwise
 binary_output = np.zeros_like(gradmag)
 binary_output[(gradmag >= thresh[0]) & (gradmag <= thresh[1])] = 1
 # return the binary image
 return binary_output
 # Define a function to threshold an image for a given range and Sobel kernel
 def gradient_direction(self, img, sobel_kernel=3, thresh=(0, np.pi/2)):
 # convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
 # take both Sobel x and y gradients
 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 # take the absolute value of the gradient direction
 absgraddir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
 # apply a threshold, and create a binary image result
 binary_output = np.zeros_like(absgraddir)
 binary_output[(absgraddir >= thresh[0]) & (absgraddir <= thresh[1])] = 1
 # return the binary image
 return binary_output
python performance object-oriented image
edited Apr 19 at 18:51


200_success
123k14142399
123k14142399
asked Apr 17 at 13:58


mo2
283
283
 
 
 2
 
 
 
 
 in- gradient_directionI see no scaling. Is this intentional?
 â Maarten Fabré
 Apr 17 at 15:08
 
 
 
 
 
 
 
 
 
 @MaartenFabré, yes, it is.
 â mo2
 Apr 21 at 21:12
 
 
 
add a comment |Â
 
 
 2
 
 
 
 
 in- gradient_directionI see no scaling. Is this intentional?
 â Maarten Fabré
 Apr 17 at 15:08
 
 
 
 
 
 
 
 
 
 @MaartenFabré, yes, it is.
 â mo2
 Apr 21 at 21:12
 
 
 
2
2
in
gradient_direction I see no scaling. Is this intentional?â Maarten Fabré
Apr 17 at 15:08
in
gradient_direction I see no scaling. Is this intentional?â Maarten Fabré
Apr 17 at 15:08
@MaartenFabré, yes, it is.
â mo2
Apr 21 at 21:12
@MaartenFabré, yes, it is.
â mo2
Apr 21 at 21:12
add a comment |Â
 2 Answers
 2
 
active
oldest
votes
up vote
5
down vote
accepted
as things are now, there is little use for the class in this case. the self argument is never used in the functions.
This is easily factored into different functions
def grayscale(img):
 return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
Whether this deserves a separate function or can be inlined is your choice. If you need to type this a lot, or if the method of grayscaling can change in the future, it will be easier to put it in a separate method.. You could also move the colorspace to the arguments to make this more versatile and also accept HSV or Luv encoded images.
def sobel_xy(gray, sobel_kernel=3, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
This calculation is done in all methods, so refactoring it is simple and effective
def gradient_magnitude(gray, sobel_kernel=3):
 return np.hypot(*sobel_xy(gray, sobel_kernel))
def gradient_direction(gray, sobel_kernel=3):
 return np.arctan2(*sobel_xy(gray, sobel_kernel))
This part is pretty straightforward. All I changed was use np.hypot to calculate the magnitude
def gradient_abs_sobel(gray, orient='x'):
 dx, dy = (1, 0) if orient == 'x' else (0, 1)
 sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy)
 return np.absolute(sobel)
def gradient_abs_sobel2(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
Depending on taste and the expense of the sobel calculation you can pick either of the 2
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(img, lower, upper):
 return (img >= lower) & (img <= upper)
Are pretty straightforward too. Instead of the np.zeros_like you can directly use the boolean array of the comparison
Now instead of calling 1 function, you just call the 4 elements subsequently. If this is too much work you can still make 1 compound method for the 3 cases.
gray = grayscale(img)
abs_sobel = gradient_abs_sobel(gray)
result = mask(scale(abs_sobel), 10, 130)
 
 
 
 
 
 
 @Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
 â mo2
 Apr 18 at 14:29
 
 
 
 
add a comment |Â
up vote
0
down vote
Thank to Maarten Fabré's feedbacks, I have rewritten the code as the following:
def grayscale(image):
 return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def sobel_xy(gray, sobel_kernel=9, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
def sobel_abs(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(image, lower, upper):
 return (image >= lower) & (image <= upper)
def gradient_abs_sobel(image, orient='x', thresh=(0, 255)):
 gray = grayscale(image)
 sobel = sobel_abs(gray, orient=orient)
 sobel_scale = scale(sobel, MAX=thresh[1], dtype=np.uint8)
 return mask(sobel_scale, thresh[0], thresh[1])
def gradient_magnitude(image, sobel_kernel=9, thresh=(0, 255)):
 gray = grayscale(image)
 gradmag = np.hypot(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=False))
 gradmag = scale(gradmag, MAX=thresh[1], dtype=np.uint8)
 return mask(gradmag, thresh[0], thresh[1])
def gradient_direction(image, sobel_kernel=15, thresh=(0, np.pi/2)): # thresh=(0.7, 1.3)
 gray = grayscale(image)
 absgraddir = np.arctan2(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=True))
 return mask(absgraddir, thresh[0], thresh[1])
def main():
 # parameters and placeholders
 args = PARSE_ARGS()
 # Choose a Sobel kernel size
 ksize = 9
 # Read images
 image = mpimg.imread(args.sand+'signs_vehicles_xygrad.jpg')
 img_solution = mpimg.imread(args.sand+'binary-combo-example.jpg')
 # Apply each of the thresholding functions
 gradx = gradient_sobel_abs(image, orient='x', sobel_kernel=ksize, thresh=(20, 100))
 grady = gradient_sobel_abs(image, orient='y', sobel_kernel=ksize, thresh=(20, 100))
 mag_binary = gradient_magnitude(image, sobel_kernel=ksize, thresh=(20, 100))
 dir_binary = gradient_direction(image, sobel_kernel=15, thresh=(0.7, 1.3))
 # combine thresholds
 combined1, combined2, combined3 = np.zeros_like(dir_binary), np.zeros_like(dir_binary), np.zeros_like(dir_binary)
 combined1[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
 combined2[((gradx == 1) & (grady == 1))] = 1
 combined3[((mag_binary == 1) & (dir_binary == 1))] = 1
 # Plot the result
 row, column = [5, 2]
 figure, axes = plt.subplots(row, column, figsize=(15, 20))
 figure.tight_layout()
 list_title_image = [['Original Image',image],
 ['Expected result', img_solution],
 ['gradx', gradx],
 ['grady', grady],
 ['mag_binary', mag_binary],
 ['dir_binary', dir_binary], 
 ['combined1', combined1],
 ['combined2', combined2],
 ['combined3', combined3],
 ['Original Image', image] ]
 for ax, img in zip(axes.flatten(), list_title_image):
 ax.imshow(img[1], cmap='gray')
 ax.set_title(img[0], fontsize=15)
 ax.axis('off')
if __name__ == '__main__':
 main()
 
 
 1
 
 
 
 
 I would replace the- thresh[0], thresh[1]by- *thresh, or change the arguments of- maskfrom- lower, upperto- thresh
 â Maarten Fabré
 Apr 19 at 19:58
 
 
 
 
 
 1
 
 
 
 
 It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
 â Cris Luengo
 Apr 20 at 18:37
 
 
 
 
 
 
 
 
 
 @CrisLuengo, done :) Bear with me, I am quite new on this platform.
 â mo2
 Apr 21 at 21:10
 
 
 
add a comment |Â
 2 Answers
 2
 
active
oldest
votes
 2 Answers
 2
 
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
as things are now, there is little use for the class in this case. the self argument is never used in the functions.
This is easily factored into different functions
def grayscale(img):
 return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
Whether this deserves a separate function or can be inlined is your choice. If you need to type this a lot, or if the method of grayscaling can change in the future, it will be easier to put it in a separate method.. You could also move the colorspace to the arguments to make this more versatile and also accept HSV or Luv encoded images.
def sobel_xy(gray, sobel_kernel=3, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
This calculation is done in all methods, so refactoring it is simple and effective
def gradient_magnitude(gray, sobel_kernel=3):
 return np.hypot(*sobel_xy(gray, sobel_kernel))
def gradient_direction(gray, sobel_kernel=3):
 return np.arctan2(*sobel_xy(gray, sobel_kernel))
This part is pretty straightforward. All I changed was use np.hypot to calculate the magnitude
def gradient_abs_sobel(gray, orient='x'):
 dx, dy = (1, 0) if orient == 'x' else (0, 1)
 sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy)
 return np.absolute(sobel)
def gradient_abs_sobel2(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
Depending on taste and the expense of the sobel calculation you can pick either of the 2
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(img, lower, upper):
 return (img >= lower) & (img <= upper)
Are pretty straightforward too. Instead of the np.zeros_like you can directly use the boolean array of the comparison
Now instead of calling 1 function, you just call the 4 elements subsequently. If this is too much work you can still make 1 compound method for the 3 cases.
gray = grayscale(img)
abs_sobel = gradient_abs_sobel(gray)
result = mask(scale(abs_sobel), 10, 130)
 
 
 
 
 
 
 @Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
 â mo2
 Apr 18 at 14:29
 
 
 
 
add a comment |Â
up vote
5
down vote
accepted
as things are now, there is little use for the class in this case. the self argument is never used in the functions.
This is easily factored into different functions
def grayscale(img):
 return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
Whether this deserves a separate function or can be inlined is your choice. If you need to type this a lot, or if the method of grayscaling can change in the future, it will be easier to put it in a separate method.. You could also move the colorspace to the arguments to make this more versatile and also accept HSV or Luv encoded images.
def sobel_xy(gray, sobel_kernel=3, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
This calculation is done in all methods, so refactoring it is simple and effective
def gradient_magnitude(gray, sobel_kernel=3):
 return np.hypot(*sobel_xy(gray, sobel_kernel))
def gradient_direction(gray, sobel_kernel=3):
 return np.arctan2(*sobel_xy(gray, sobel_kernel))
This part is pretty straightforward. All I changed was use np.hypot to calculate the magnitude
def gradient_abs_sobel(gray, orient='x'):
 dx, dy = (1, 0) if orient == 'x' else (0, 1)
 sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy)
 return np.absolute(sobel)
def gradient_abs_sobel2(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
Depending on taste and the expense of the sobel calculation you can pick either of the 2
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(img, lower, upper):
 return (img >= lower) & (img <= upper)
Are pretty straightforward too. Instead of the np.zeros_like you can directly use the boolean array of the comparison
Now instead of calling 1 function, you just call the 4 elements subsequently. If this is too much work you can still make 1 compound method for the 3 cases.
gray = grayscale(img)
abs_sobel = gradient_abs_sobel(gray)
result = mask(scale(abs_sobel), 10, 130)
 
 
 
 
 
 
 @Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
 â mo2
 Apr 18 at 14:29
 
 
 
 
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
as things are now, there is little use for the class in this case. the self argument is never used in the functions.
This is easily factored into different functions
def grayscale(img):
 return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
Whether this deserves a separate function or can be inlined is your choice. If you need to type this a lot, or if the method of grayscaling can change in the future, it will be easier to put it in a separate method.. You could also move the colorspace to the arguments to make this more versatile and also accept HSV or Luv encoded images.
def sobel_xy(gray, sobel_kernel=3, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
This calculation is done in all methods, so refactoring it is simple and effective
def gradient_magnitude(gray, sobel_kernel=3):
 return np.hypot(*sobel_xy(gray, sobel_kernel))
def gradient_direction(gray, sobel_kernel=3):
 return np.arctan2(*sobel_xy(gray, sobel_kernel))
This part is pretty straightforward. All I changed was use np.hypot to calculate the magnitude
def gradient_abs_sobel(gray, orient='x'):
 dx, dy = (1, 0) if orient == 'x' else (0, 1)
 sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy)
 return np.absolute(sobel)
def gradient_abs_sobel2(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
Depending on taste and the expense of the sobel calculation you can pick either of the 2
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(img, lower, upper):
 return (img >= lower) & (img <= upper)
Are pretty straightforward too. Instead of the np.zeros_like you can directly use the boolean array of the comparison
Now instead of calling 1 function, you just call the 4 elements subsequently. If this is too much work you can still make 1 compound method for the 3 cases.
gray = grayscale(img)
abs_sobel = gradient_abs_sobel(gray)
result = mask(scale(abs_sobel), 10, 130)
as things are now, there is little use for the class in this case. the self argument is never used in the functions.
This is easily factored into different functions
def grayscale(img):
 return cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
Whether this deserves a separate function or can be inlined is your choice. If you need to type this a lot, or if the method of grayscaling can change in the future, it will be easier to put it in a separate method.. You could also move the colorspace to the arguments to make this more versatile and also accept HSV or Luv encoded images.
def sobel_xy(gray, sobel_kernel=3, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
This calculation is done in all methods, so refactoring it is simple and effective
def gradient_magnitude(gray, sobel_kernel=3):
 return np.hypot(*sobel_xy(gray, sobel_kernel))
def gradient_direction(gray, sobel_kernel=3):
 return np.arctan2(*sobel_xy(gray, sobel_kernel))
This part is pretty straightforward. All I changed was use np.hypot to calculate the magnitude
def gradient_abs_sobel(gray, orient='x'):
 dx, dy = (1, 0) if orient == 'x' else (0, 1)
 sobel = cv2.Sobel(gray, cv2.CV_64F, dx, dy)
 return np.absolute(sobel)
def gradient_abs_sobel2(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
Depending on taste and the expense of the sobel calculation you can pick either of the 2
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(img, lower, upper):
 return (img >= lower) & (img <= upper)
Are pretty straightforward too. Instead of the np.zeros_like you can directly use the boolean array of the comparison
Now instead of calling 1 function, you just call the 4 elements subsequently. If this is too much work you can still make 1 compound method for the 3 cases.
gray = grayscale(img)
abs_sobel = gradient_abs_sobel(gray)
result = mask(scale(abs_sobel), 10, 130)
edited Apr 18 at 7:45
answered Apr 17 at 15:42
Maarten Fabré
3,204214
3,204214
 
 
 
 
 
 
 @Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
 â mo2
 Apr 18 at 14:29
 
 
 
 
add a comment |Â
 
 
 
 
 
 
 @Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
 â mo2
 Apr 18 at 14:29
 
 
 
 
@Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
â mo2
Apr 18 at 14:29
@Maarten Fabré, thank you for your feedback!! I particularly enjoyed the two following lines and the way you cut the code: lines = 1 : ' dx, dy = (1, 0) if orient == 'x' else (0, 1) ' ; 2 : ' orientation = 'x': 0,'y': 1[orient] '
â mo2
Apr 18 at 14:29
add a comment |Â
up vote
0
down vote
Thank to Maarten Fabré's feedbacks, I have rewritten the code as the following:
def grayscale(image):
 return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def sobel_xy(gray, sobel_kernel=9, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
def sobel_abs(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(image, lower, upper):
 return (image >= lower) & (image <= upper)
def gradient_abs_sobel(image, orient='x', thresh=(0, 255)):
 gray = grayscale(image)
 sobel = sobel_abs(gray, orient=orient)
 sobel_scale = scale(sobel, MAX=thresh[1], dtype=np.uint8)
 return mask(sobel_scale, thresh[0], thresh[1])
def gradient_magnitude(image, sobel_kernel=9, thresh=(0, 255)):
 gray = grayscale(image)
 gradmag = np.hypot(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=False))
 gradmag = scale(gradmag, MAX=thresh[1], dtype=np.uint8)
 return mask(gradmag, thresh[0], thresh[1])
def gradient_direction(image, sobel_kernel=15, thresh=(0, np.pi/2)): # thresh=(0.7, 1.3)
 gray = grayscale(image)
 absgraddir = np.arctan2(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=True))
 return mask(absgraddir, thresh[0], thresh[1])
def main():
 # parameters and placeholders
 args = PARSE_ARGS()
 # Choose a Sobel kernel size
 ksize = 9
 # Read images
 image = mpimg.imread(args.sand+'signs_vehicles_xygrad.jpg')
 img_solution = mpimg.imread(args.sand+'binary-combo-example.jpg')
 # Apply each of the thresholding functions
 gradx = gradient_sobel_abs(image, orient='x', sobel_kernel=ksize, thresh=(20, 100))
 grady = gradient_sobel_abs(image, orient='y', sobel_kernel=ksize, thresh=(20, 100))
 mag_binary = gradient_magnitude(image, sobel_kernel=ksize, thresh=(20, 100))
 dir_binary = gradient_direction(image, sobel_kernel=15, thresh=(0.7, 1.3))
 # combine thresholds
 combined1, combined2, combined3 = np.zeros_like(dir_binary), np.zeros_like(dir_binary), np.zeros_like(dir_binary)
 combined1[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
 combined2[((gradx == 1) & (grady == 1))] = 1
 combined3[((mag_binary == 1) & (dir_binary == 1))] = 1
 # Plot the result
 row, column = [5, 2]
 figure, axes = plt.subplots(row, column, figsize=(15, 20))
 figure.tight_layout()
 list_title_image = [['Original Image',image],
 ['Expected result', img_solution],
 ['gradx', gradx],
 ['grady', grady],
 ['mag_binary', mag_binary],
 ['dir_binary', dir_binary], 
 ['combined1', combined1],
 ['combined2', combined2],
 ['combined3', combined3],
 ['Original Image', image] ]
 for ax, img in zip(axes.flatten(), list_title_image):
 ax.imshow(img[1], cmap='gray')
 ax.set_title(img[0], fontsize=15)
 ax.axis('off')
if __name__ == '__main__':
 main()
 
 
 1
 
 
 
 
 I would replace the- thresh[0], thresh[1]by- *thresh, or change the arguments of- maskfrom- lower, upperto- thresh
 â Maarten Fabré
 Apr 19 at 19:58
 
 
 
 
 
 1
 
 
 
 
 It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
 â Cris Luengo
 Apr 20 at 18:37
 
 
 
 
 
 
 
 
 
 @CrisLuengo, done :) Bear with me, I am quite new on this platform.
 â mo2
 Apr 21 at 21:10
 
 
 
add a comment |Â
up vote
0
down vote
Thank to Maarten Fabré's feedbacks, I have rewritten the code as the following:
def grayscale(image):
 return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def sobel_xy(gray, sobel_kernel=9, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
def sobel_abs(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(image, lower, upper):
 return (image >= lower) & (image <= upper)
def gradient_abs_sobel(image, orient='x', thresh=(0, 255)):
 gray = grayscale(image)
 sobel = sobel_abs(gray, orient=orient)
 sobel_scale = scale(sobel, MAX=thresh[1], dtype=np.uint8)
 return mask(sobel_scale, thresh[0], thresh[1])
def gradient_magnitude(image, sobel_kernel=9, thresh=(0, 255)):
 gray = grayscale(image)
 gradmag = np.hypot(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=False))
 gradmag = scale(gradmag, MAX=thresh[1], dtype=np.uint8)
 return mask(gradmag, thresh[0], thresh[1])
def gradient_direction(image, sobel_kernel=15, thresh=(0, np.pi/2)): # thresh=(0.7, 1.3)
 gray = grayscale(image)
 absgraddir = np.arctan2(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=True))
 return mask(absgraddir, thresh[0], thresh[1])
def main():
 # parameters and placeholders
 args = PARSE_ARGS()
 # Choose a Sobel kernel size
 ksize = 9
 # Read images
 image = mpimg.imread(args.sand+'signs_vehicles_xygrad.jpg')
 img_solution = mpimg.imread(args.sand+'binary-combo-example.jpg')
 # Apply each of the thresholding functions
 gradx = gradient_sobel_abs(image, orient='x', sobel_kernel=ksize, thresh=(20, 100))
 grady = gradient_sobel_abs(image, orient='y', sobel_kernel=ksize, thresh=(20, 100))
 mag_binary = gradient_magnitude(image, sobel_kernel=ksize, thresh=(20, 100))
 dir_binary = gradient_direction(image, sobel_kernel=15, thresh=(0.7, 1.3))
 # combine thresholds
 combined1, combined2, combined3 = np.zeros_like(dir_binary), np.zeros_like(dir_binary), np.zeros_like(dir_binary)
 combined1[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
 combined2[((gradx == 1) & (grady == 1))] = 1
 combined3[((mag_binary == 1) & (dir_binary == 1))] = 1
 # Plot the result
 row, column = [5, 2]
 figure, axes = plt.subplots(row, column, figsize=(15, 20))
 figure.tight_layout()
 list_title_image = [['Original Image',image],
 ['Expected result', img_solution],
 ['gradx', gradx],
 ['grady', grady],
 ['mag_binary', mag_binary],
 ['dir_binary', dir_binary], 
 ['combined1', combined1],
 ['combined2', combined2],
 ['combined3', combined3],
 ['Original Image', image] ]
 for ax, img in zip(axes.flatten(), list_title_image):
 ax.imshow(img[1], cmap='gray')
 ax.set_title(img[0], fontsize=15)
 ax.axis('off')
if __name__ == '__main__':
 main()
 
 
 1
 
 
 
 
 I would replace the- thresh[0], thresh[1]by- *thresh, or change the arguments of- maskfrom- lower, upperto- thresh
 â Maarten Fabré
 Apr 19 at 19:58
 
 
 
 
 
 1
 
 
 
 
 It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
 â Cris Luengo
 Apr 20 at 18:37
 
 
 
 
 
 
 
 
 
 @CrisLuengo, done :) Bear with me, I am quite new on this platform.
 â mo2
 Apr 21 at 21:10
 
 
 
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Thank to Maarten Fabré's feedbacks, I have rewritten the code as the following:
def grayscale(image):
 return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def sobel_xy(gray, sobel_kernel=9, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
def sobel_abs(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(image, lower, upper):
 return (image >= lower) & (image <= upper)
def gradient_abs_sobel(image, orient='x', thresh=(0, 255)):
 gray = grayscale(image)
 sobel = sobel_abs(gray, orient=orient)
 sobel_scale = scale(sobel, MAX=thresh[1], dtype=np.uint8)
 return mask(sobel_scale, thresh[0], thresh[1])
def gradient_magnitude(image, sobel_kernel=9, thresh=(0, 255)):
 gray = grayscale(image)
 gradmag = np.hypot(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=False))
 gradmag = scale(gradmag, MAX=thresh[1], dtype=np.uint8)
 return mask(gradmag, thresh[0], thresh[1])
def gradient_direction(image, sobel_kernel=15, thresh=(0, np.pi/2)): # thresh=(0.7, 1.3)
 gray = grayscale(image)
 absgraddir = np.arctan2(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=True))
 return mask(absgraddir, thresh[0], thresh[1])
def main():
 # parameters and placeholders
 args = PARSE_ARGS()
 # Choose a Sobel kernel size
 ksize = 9
 # Read images
 image = mpimg.imread(args.sand+'signs_vehicles_xygrad.jpg')
 img_solution = mpimg.imread(args.sand+'binary-combo-example.jpg')
 # Apply each of the thresholding functions
 gradx = gradient_sobel_abs(image, orient='x', sobel_kernel=ksize, thresh=(20, 100))
 grady = gradient_sobel_abs(image, orient='y', sobel_kernel=ksize, thresh=(20, 100))
 mag_binary = gradient_magnitude(image, sobel_kernel=ksize, thresh=(20, 100))
 dir_binary = gradient_direction(image, sobel_kernel=15, thresh=(0.7, 1.3))
 # combine thresholds
 combined1, combined2, combined3 = np.zeros_like(dir_binary), np.zeros_like(dir_binary), np.zeros_like(dir_binary)
 combined1[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
 combined2[((gradx == 1) & (grady == 1))] = 1
 combined3[((mag_binary == 1) & (dir_binary == 1))] = 1
 # Plot the result
 row, column = [5, 2]
 figure, axes = plt.subplots(row, column, figsize=(15, 20))
 figure.tight_layout()
 list_title_image = [['Original Image',image],
 ['Expected result', img_solution],
 ['gradx', gradx],
 ['grady', grady],
 ['mag_binary', mag_binary],
 ['dir_binary', dir_binary], 
 ['combined1', combined1],
 ['combined2', combined2],
 ['combined3', combined3],
 ['Original Image', image] ]
 for ax, img in zip(axes.flatten(), list_title_image):
 ax.imshow(img[1], cmap='gray')
 ax.set_title(img[0], fontsize=15)
 ax.axis('off')
if __name__ == '__main__':
 main()
Thank to Maarten Fabré's feedbacks, I have rewritten the code as the following:
def grayscale(image):
 return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
def sobel_xy(gray, sobel_kernel=9, absolute=True):
 sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
 sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
 if absolute:
 sobel_x, sobel_y = np.absolute(sobel_x), np.absolute(sobel_y)
 return sobel_x, sobel_y
def sobel_abs(gray, orient='x'):
 orientation = 'x': 0,'y': 1[orient]
 sobel = sobel_xy(gray)
 return sobel[orientation]
def scale(sobel, MAX=255, dtype=np.uint8):
 return dtype(MAX * sobel / np.max(sobel))
def mask(image, lower, upper):
 return (image >= lower) & (image <= upper)
def gradient_abs_sobel(image, orient='x', thresh=(0, 255)):
 gray = grayscale(image)
 sobel = sobel_abs(gray, orient=orient)
 sobel_scale = scale(sobel, MAX=thresh[1], dtype=np.uint8)
 return mask(sobel_scale, thresh[0], thresh[1])
def gradient_magnitude(image, sobel_kernel=9, thresh=(0, 255)):
 gray = grayscale(image)
 gradmag = np.hypot(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=False))
 gradmag = scale(gradmag, MAX=thresh[1], dtype=np.uint8)
 return mask(gradmag, thresh[0], thresh[1])
def gradient_direction(image, sobel_kernel=15, thresh=(0, np.pi/2)): # thresh=(0.7, 1.3)
 gray = grayscale(image)
 absgraddir = np.arctan2(*sobel_xy(gray, sobel_kernel=sobel_kernel, absolute=True))
 return mask(absgraddir, thresh[0], thresh[1])
def main():
 # parameters and placeholders
 args = PARSE_ARGS()
 # Choose a Sobel kernel size
 ksize = 9
 # Read images
 image = mpimg.imread(args.sand+'signs_vehicles_xygrad.jpg')
 img_solution = mpimg.imread(args.sand+'binary-combo-example.jpg')
 # Apply each of the thresholding functions
 gradx = gradient_sobel_abs(image, orient='x', sobel_kernel=ksize, thresh=(20, 100))
 grady = gradient_sobel_abs(image, orient='y', sobel_kernel=ksize, thresh=(20, 100))
 mag_binary = gradient_magnitude(image, sobel_kernel=ksize, thresh=(20, 100))
 dir_binary = gradient_direction(image, sobel_kernel=15, thresh=(0.7, 1.3))
 # combine thresholds
 combined1, combined2, combined3 = np.zeros_like(dir_binary), np.zeros_like(dir_binary), np.zeros_like(dir_binary)
 combined1[((gradx == 1) & (grady == 1)) | ((mag_binary == 1) & (dir_binary == 1))] = 1
 combined2[((gradx == 1) & (grady == 1))] = 1
 combined3[((mag_binary == 1) & (dir_binary == 1))] = 1
 # Plot the result
 row, column = [5, 2]
 figure, axes = plt.subplots(row, column, figsize=(15, 20))
 figure.tight_layout()
 list_title_image = [['Original Image',image],
 ['Expected result', img_solution],
 ['gradx', gradx],
 ['grady', grady],
 ['mag_binary', mag_binary],
 ['dir_binary', dir_binary], 
 ['combined1', combined1],
 ['combined2', combined2],
 ['combined3', combined3],
 ['Original Image', image] ]
 for ax, img in zip(axes.flatten(), list_title_image):
 ax.imshow(img[1], cmap='gray')
 ax.set_title(img[0], fontsize=15)
 ax.axis('off')
if __name__ == '__main__':
 main()
answered Apr 19 at 16:21


mo2
283
283
 
 
 1
 
 
 
 
 I would replace the- thresh[0], thresh[1]by- *thresh, or change the arguments of- maskfrom- lower, upperto- thresh
 â Maarten Fabré
 Apr 19 at 19:58
 
 
 
 
 
 1
 
 
 
 
 It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
 â Cris Luengo
 Apr 20 at 18:37
 
 
 
 
 
 
 
 
 
 @CrisLuengo, done :) Bear with me, I am quite new on this platform.
 â mo2
 Apr 21 at 21:10
 
 
 
add a comment |Â
 
 
 1
 
 
 
 
 I would replace the- thresh[0], thresh[1]by- *thresh, or change the arguments of- maskfrom- lower, upperto- thresh
 â Maarten Fabré
 Apr 19 at 19:58
 
 
 
 
 
 1
 
 
 
 
 It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
 â Cris Luengo
 Apr 20 at 18:37
 
 
 
 
 
 
 
 
 
 @CrisLuengo, done :) Bear with me, I am quite new on this platform.
 â mo2
 Apr 21 at 21:10
 
 
 
1
1
I would replace the
thresh[0], thresh[1] by *thresh, or change the arguments of mask from lower, upper to threshâ Maarten Fabré
Apr 19 at 19:58
I would replace the
thresh[0], thresh[1] by *thresh, or change the arguments of mask from lower, upper to threshâ Maarten Fabré
Apr 19 at 19:58
1
1
It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
â Cris Luengo
Apr 20 at 18:37
It's nice that you posted the updated code, but you should accept Maarten's answer, as it helped you. This will give Maarten the rep he deserves.
â Cris Luengo
Apr 20 at 18:37
@CrisLuengo, done :) Bear with me, I am quite new on this platform.
â mo2
Apr 21 at 21:10
@CrisLuengo, done :) Bear with me, I am quite new on this platform.
â mo2
Apr 21 at 21:10
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192292%2fthreshold-an-image-for-a-given-range-and-sobel-kernel%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
2
in
gradient_directionI see no scaling. Is this intentional?â Maarten Fabré
Apr 17 at 15:08
@MaartenFabré, yes, it is.
â mo2
Apr 21 at 21:12