Nyyir
Nyyir

Reputation: 43

Not able to get the center of an object using openCV

I am not able to properly find the center of a triangle using openCV, the center point was drawn at the bottom tip of the triangle. Can anyone help me what is wrong in the code?

import cv2
import numpy as np

import stackImages as stack

img = cv2.imread('triangle.jpg',0)
NewImg = img.copy()
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)

cnt = contours[0]
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

cv2.circle(NewImg, (cx, cy), 2, (0, 0, 255), 3)

cv2.putText(NewImg, "centroid", (cx, cy),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)       

while (True):
    #imgStack = stack.stackImages(0.8,([img, NewImg]))
    cv2.imshow('Sample', NewImg)
    if cv2.waitKey(1) & 0xFF == ord('q'):    
        cv2.destroyAllWindows()
        break

Original Image: enter image description here

Processed Image: enter image description here

Upvotes: 2

Views: 188

Answers (4)

Barak Itkin
Barak Itkin

Reputation: 4877

You may find multiple contours, and you want the one with the biggest area.

# Sort all contours by increasing area
contours_s = sorted(contours, key=cv2.contourArea)

# Find the second largest contour (the largest is the entire image
cnt = contours_s[-2]

copy = cv2.cvtColor(thresh, cv2.COLOR_GRAY2RGB)
cv2.drawContours(copy, [cnt], 0, (0, 0, 255))
cv2.imshow(copy)

enter image description here

Upvotes: 2

amras
amras

Reputation: 1619

If you want to have triangle as the largest contour to be returned, you can apply edge detection. Also its better to use grab_contours from imutils to avoid errors in getting the contours.

import cv2
import numpy as np
import imutils

img = cv2.imread('triangle.jpg',0)
NewImg = img.copy()
blur = cv2.GaussianBlur(img, (3, 3), 0)
edged = cv2.Canny(blur, 50, 200)

cnts = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnt = sorted(cnts, key = cv2.contourArea, reverse = True)[0]    

M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

cv2.circle(NewImg, (cx, cy), 2, (0, 0, 255), 3)

cv2.putText(NewImg, "centroid", (cx, cy),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)       

while (True):
    cv2.imshow('Sample', NewImg)
    if cv2.waitKey(1) & 0xFF == ord('q'):    
        cv2.destroyAllWindows()
        break

Upvotes: 1

Yunus Temurlenk
Yunus Temurlenk

Reputation: 4367

There is nothing wrong with your code. Just cos of you didn't choose the mode for findContours() and its choosing the default one and finding outer or some other contours. Just change your line with this:

contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

Upvotes: 1

Vardan Agarwal
Vardan Agarwal

Reputation: 2191

In Opencv the object needs to be in white and the background black, so when you are applying threshold use cv2.THRESH_BINARY_INV as the third argument.

Upvotes: 1

Related Questions