pythonopencvimage-processingcomputer-visioncorner-detection

Corner detection in opencv


I was trying to detect all the corners in the image using harris corner detection in opencv(python). But due to the thickness of the line , I am getting multiple corners in a single corner . Is there something I can do to make this right.

code

import numpy as np
import cv2 as cv
filename = 'Triangle.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
#result is dilated for marking the corners, not important
dst = cv.dilate(dst,None)
# Threshold for an optimal value, it may vary depending on the image.
img[dst>0.01*dst.max()]=[0,0,255]
cv.imshow('dst',img)
if cv.waitKey(0) & 0xff == 27:
    cv.destroyAllWindows()

This is the input image

Output image(that i got)


Solution

  • If your expectation is to obtain a single corner point at every line intersection, then the following is a simple approach.

    Current scenario:

    # visualize the corners
    mask = np.zeros_like(gray)
    mask[dst>0.01*dst.max()] = 255
    

    enter image description here

    In the above, there are many (supposedly) corner points close to each other.

    Approach:

    The idea now is to preserve only one point that is in close proximity to each other, while discarding the rest. To do so, I calculate the distance of each corner to every other and keep those that exceed a threshold.

    # storing coordinate positions of all points in a list
    coordinates = np.argwhere(mask)
    coor_list = coordinates.tolist()
    
    # points beyond this threshold are preserved
    thresh = 20
    
    # function to compute distance between 2 points
    def distance(pt1, pt2):
        (x1, y1), (x2, y2) = pt1, pt2
        dist = math.sqrt( (x2 - x1)**2 + (y2 - y1)**2 )
        return dist
    
    # 
    coor_list_2 = coor_list.copy()
    
    # iterate for every 2 points
    i = 1    
    for pt1 in coor_list:
        for pt2 in coor_list[i::1]:
            if(distance(pt1, pt2) < thresh):
              # to avoid removing a point if already removed
              try:
                coor_list_2.remove(pt2)      
              except:
                pass
        i+=1
    
    # draw final corners
    img2 = img.copy()
    for pt in coor_list_2:
        img2 = cv2.circle(img2, tuple(reversed(pt)), 3, (0, 0, 255), -1)
    

    enter image description here

    Suggestions:

    To get more accurate result you can try finding the mean of all the points within a certain proximity. These would coincide close to the intersection of lines.