The problem
As shown in the image, I am trying to detect road marking arrows in images using OpenCV. The arrows are always of the same size and shape but can appear in different orientations.
These are the five possible arrow types I need to detect:
- straight only
- left turn only
- right turn only
- straight or right turn
- straight or left turn
What I’ve tried:
Approach 1: cv.matchTemplate
using TM_CCORR_NORMED
cv.matchTemplate
using TM_CCORR_NORMED
. This only worked if both my image and template are both the same orientation without any preprocessing.
Interestingly, applying the same preprocessing steps on both the image and template had reduced the correlation (Canny detection) when doing cv.matchTemplate
.
Furthermore, matchTemplate
is not rotation invariant so it could not detect rotated arrows.
Approach 2: These two Stack Overflow posts
As my arrows are of a more custom shape, the code provided did not work.
Approach 3: Hough Line Transform and Contour Detection
I am stuck with this approach as I am unable to figure out the code to be able to detect the five possible combinations of arrows.
import cv2
import numpy as np
# Load Image
img = cv2.imread('path_to_image')
# Preprocessing
processed = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
processed = cv2.bilateralFilter(processed, 11, 75, 75)
processed = cv2.Canny(processed, 50, 150)
kernel = np.ones((3, 3), np.uint8)
processed = cv2.morphologyEx(processed, cv2.MORPH_CLOSE, kernel, iterations=1)
# Hough Line Transform
lines = cv2.HoughLinesP(processed, 1, np.pi/180, threshold=50, minLineLength=30, maxLineGap=10)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
# Contour Detection
contours, _ = cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
if len(approx) > 5: # Rough filter for arrow shapes
cv2.drawContours(img, [approx], 0, (255, 0, 0), 2)
# Display Results
cv2.imshow('Detected Arrows', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Additional Context
-
The image provided is a zoomed-in version of a much larger 8,000 × 8,000 pixel image. The full image contains a lot more noise, including road markings and intersections, but the road markings themselves seem distinct from the rest. The arrows themselves are much smaller in the full image (roughly 7 KB when cropping out a single arrow).
-
I’m open to having separate algorithms to detect each of the five arrow combinations separately instead of a generalized approach.
-
I am open to approaches other than OpenCV but I do not have any annotated data to work with. Creating a training dataset is not feasible due to time constraints.