Batata
Batata

Reputation: 96

Finding edges of road using opencv

I am interested in finding the edges of the road. The output image should have only edges marked. Here is one of my input image:

enter image description here

But the edges in output are either distorted or have lot of noise. Here is its output:

output

I have tried applying watershed algorithm, but it does not detect the roads properly.

Here is my code:

import cv2
import numpy as np

img = cv2.imread('road2.jpg',0)

ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(thresh1,kernel,iterations = 1)
#Removing noise from image
blur = cv2.blur(img,(5,5))
#finding edges using edge detection
edges = cv2.Canny(blur, 100 ,200)


laplacian = cv2.Laplacian(edges, cv2.CV_8UC1)
sobely = cv2.Sobel(laplacian,cv2.CV_8UC1, 0, 1, ksize=5)
im2, contours, hierarchy = cv2.findContours(sobely,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

frame = cv2.drawContours(im2, contours, -1, (255,0,0), 3)
cv2.imshow('window',frame)

cv2.waitKey(0)
cv2.destroyAllWindows()

What should do inoder to mark only the edges. I want only the edges in the output beacuse I would later need these edges to find the middle lane of the road.

Upvotes: 3

Views: 3846

Answers (1)

Saurav Gupta
Saurav Gupta

Reputation: 535

Result can be seen here. Not perfect, but best I could do. Idea taken from here

The code works for this image on the assumption that:

If there are no cars on the road, then the two markings(left and right), will meet at a vanishing point on the horizon and form a triangle. So, I keep only the largest contour that can be approximated by a triangle.

import cv2
import numpy as np

img = cv2.imread('road2.jpg',0)

ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(thresh1,kernel,iterations = 1)
#Removing noise from image
blur = cv2.blur(img,(5,5))
#finding edges using edge detection
edges = cv2.Canny(blur, 100 ,200)


laplacian = cv2.Laplacian(edges, cv2.CV_8UC1)
sobely = cv2.Sobel(laplacian,cv2.CV_8UC1, 0, 1, ksize=5)

# Do a dilation and erosion to accentuate the triangle shape
dilated = cv2.dilate(sobely,kernel,iterations = 1)
erosion = cv2.erode(dilated,kernel,iterations = 1)

im2, contours, hierarchy =  cv2.findContours(erosion,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#keep 10 largest contours
cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:10]
screenCnt = None

for c in cnts:
    # approximate the contour
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    # if our approximated contour has three points, then
    # it must be the road markings
    if len(approx) == 3:
        screenCnt = approx
        break
cv2.drawContours(img, [screenCnt], -1, (0, 255, 0), 3)
cv2.imshow("Road markings", img)
cv2.waitKey(0)

Upvotes: 3

Related Questions