Self-driving car: Edge detection

Javier Abellán Abenza
Neurosapiens
Published in
3 min readDec 27, 2018
Photo by dan carlson on Unsplash

1. Convert image to grayscale

To detect edeges we have to pass the image to black and white

gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

2. Reduce noise

blur = cv2.GaussianBlur(gray,(5,5), 0)

Alternative to GaussianBlur: bilateralFilter keeps the edges sharper.

3. Detect edges: Sobel filter (NOT USED)

The Sobel filter is very commonly used in edge detection and in finding patterns in intensity in an image. Applying a Sobel filter to an image is a way of taking (an approximation) of the derivative of the image in the x or y direction, separately. The operators look as follows.

Derivative of the gaussian
Sobel filters
filtered_image = cv2.filter2D(gray, -1, filters[i])

3. Detect edges: Canny

Canny Edge Detection is a popular edge detection algorithm. It was developed by John F. Canny in 1986. It is a multi-stage algorithm and we will go through each stages.

  1. Noise Reduction: Since edge detection is susceptible to noise in the image, first step is to remove the noise in the image with a 5x5 Gaussian filter.
  2. Finding Intensity Gradient of the Image: Smoothened image is then filtered with a Sobel kernel in both horizontal and vertical direction.
  3. Non-maximum suppression (thinning): Zero out all pixels that are not the maximum along the direction of the gradient (look at 1 pixel on each side)
  4. Hysteresis Thresholding: This stage decides which are all edges are really edges and which are not. For this, we need two threshold values, minVal and maxVal.
canny_wide  = cv2.Canny(gray, 30, 100)
canny_tight = cv2.Canny(gray, 200, 240)
canny = cv2.Canny(blur, 50, 150)

4. Isolate region of interest

############################## Get region of interest mask
height = image.shape[0]
width = image.shape[0]
triangle = np.array([(200, height), (500,250), (1200,height)])
square = np.array([(0,height),(465,320),(475,320),(width,height)])
mask = np.zeros_like(image)
cv2.fillPoly(mask, triangle, 255)
############################## Get edges in the mask
road_edges = cv2.bitwise_and(canny, mask)

5. Finding lines: Hough transform

Hough space: A 2D plane where each point represents a line, the x-axis is the slope (m) and the y-axis, the intercept (n).

lines = cv2.HoughLinesP(
image = road_edges, # Input image
rho = 2, # Distance resolution
theta = np.pi/180, # Angle resolution
threshold = 45 # 100 # Min intersections
lines = np.array([]), # Output vector of lines
minLineLength = 40, # Minimum line length
maxLineGap = 100) # 5 # Max gap between line points

Then display the lines

line_image = np.zeros_like(image)
for line in lines:
x1, x2, y1, y2 = line.reshape(4)
cv2.line(line_image, (x1, y1), (x2, y2),
color=(255,0,0), thickness=10)
image_with_lines = cv2.addWeighted(line_image, 0.8, image, 1, 1)

6. Average lines

The goal is to have only 2 lines. Note if the slope is negative corresponds to the left side, and a positive slope corresponds to the right side.

--

--

Javier Abellán Abenza
Neurosapiens

M.S. Computer Science student interested in deep learning