Search code examples
pythonopencvcanny-operator

Separating the coordinates of multiple canny edge detections from opencv in python


I am currently running canny edge detections and am detecting two square objects. I detect the edges and list the coordinates using

colourMap = cv2.imread('Colour_Map_Generated2.jpg',0)
edges = cv2.Canny(colourMap,10,20) 

cv2.imwrite('/home/pi/Desktop/edgesDetected.jpg',edges)

indices = np.where(edges != [0])
coordinates = zip(indices[0], indices[1])

however this method puts all the coordinates together in one list, how do i put the coordinates of each square in a separate array?

So far i have attempted to determine 2 ROI's however that detects the whole image when i tried therefore was unsuccessful, moreover if i was to hard set the quantity of ROI's it wouldn't work either as this system may be detecting different amounts of squares. I also attempted to use blob detection but that seemed to require me to fill in the detected squares which seems like a waste of time when i already have the coordinates.

EDIT

Here is an example image with the edge detections in


Solution

  • I'm using findContours to get the points for each rectangle. Since findContours will give the inner and outer contour of a hollow shape, we have to remove duplicates by checking for similar perimeters.

    enter image description here

    import cv2
    import numpy as np
    
    # load image
    img = cv2.imread("rectangles.png");
    
    # make a mask
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
    mask = cv2.inRange(gray, 100, 255);
    
    # get contours # OpenCV 3.4, if you're using OpenCV 2 or 4, it returns (contours, _)
    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
    print(len(contours));
    
    # remove contours with very similar perimeters (we get back inner and outer contours)
    cutoff_percent = 0.05;
    no_dupes = [];
    for con in contours:
        perim = cv2.arcLength(con, closed = True);
        # check for duplicate
        dupe_flag = False;
        for dupe in no_dupes:
            dupe_perim = cv2.arcLength(dupe, closed = True);
            if abs(dupe_perim - perim) < cutoff_percent * perim:
                dupe_flag = True;
                break;
    
        # add to list
        if not dupe_flag:
            no_dupes.append(con);
    print(len(no_dupes));
    
    # draw each one sequentially
    blank = np.zeros_like(img);
    cv2.imwrite("blank.png", blank);
    for a in range(len(no_dupes)):
        cv2.drawContours(blank, [no_dupes[a]], -1, (200, 200, 0), 1);
        cv2.imshow("blank", blank);
        cv2.waitKey(0);
    
    # show
    cv2.imshow("Image", img);
    cv2.waitKey(0);