Qi Li
Qi Li

Reputation: 1

breaking contour across image border into lines

I use the function findContours to find the borders of the driveway. However, since the driveway usually comes across the image, I get polygons like this. What I really like is line instances, so I am wondering is there any way to break the polygon into line instances.

Upvotes: 0

Views: 397

Answers (1)

Ian Chu
Ian Chu

Reputation: 3143

You can use approxPolyDP to simplify a contour down into larger lines.

The epsilon value specifies the minimum length for each line segment.

enter image description here

import cv2
import numpy as np
import random

# turns a list into a tuple
def tup(arr):
    return (int(arr[0]), int(arr[1]));

# load image
img = cv2.imread("rect.png");
img = img[:,1:]; # there's a weird thing on the left side

# get mask
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
mask = cv2.inRange(gray, 10, 255);

# dilate and erode to clean up lines
kernel = np.ones((3,3), np.uint8);
mask = cv2.dilate(mask, kernel, iterations = 2);
mask = cv2.erode(mask, kernel, iterations = 2);

# get contour # OpenCV 3.4, Other versions will return (countours, _)
_, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);

# get approximate lines
epsilon = 0.005*cv2.arcLength(contours[0],True); # epsilon is the minimum length of the line
approx = cv2.approxPolyDP(contours[0],epsilon,True);

# draw lines
for a in range(len(approx)):
    color = [random.randint(0,255) for col in range(3)];
    start = approx[a-1][0]; # points have an extra layer of brackets
    end = approx[a][0];
    cv2.line(img, tup(start), tup(end), color, 2);
    
# show
cv2.imshow("img", img);
cv2.waitKey(0);

Upvotes: 1

Related Questions