user3377126
user3377126

Reputation: 2171

Having trouble with orientation detection in OpenCV

I am trying to make a computer vision script that detects the orientation of objects. It works a majority of the time, but it seems that it is not able to have the same success for certain images.

This script relies on blurring and Canny edge detection to find the contours.

Working example:

enter image description here

Part which it fails: enter image description here

enter image description here

For the part where it fails, it two lines for one of the same shapes and it completely ignores one of the others shapes.

Main code:

import cv2
from imgops import imutils
import CVAlgo

z = 'am'

path = 'images/pca.jpg'
#path = 'images/pca2.jpg'

img = cv2.imread(path)
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img = imutils.resize(img, height = 600)
imgray = imutils.resize(img, height = 600)

final = img.copy()

thresh, imgray = CVAlgo.filtering(img, imgray, z)


__ , contours, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# Iterate through all contours
test = CVAlgo.cnt_gui(final, contours)

#cv2.imwrite('1.jpg', final)

cv2.imshow('thresh', thresh)
cv2.imshow('contours', final)
cv2.waitKey(0)

CVAlgo.py

import cv2
from numpy import *
from pylab import *
from imgops import imutils
import math

def invert_img(img):
    img = (255-img)
    return img


def canny(imgray):
    imgray = cv2.GaussianBlur(imgray, (11,11), 200)
    canny_low = 0
    canny_high = 100

    thresh = cv2.Canny(imgray,canny_low,canny_high)
    return thresh

def cnt_gui(img, contours):
    cnts = sorted(contours, key = cv2.contourArea, reverse = True)

    for i in range(0,len(cnts)):
        sel_cnts = sorted(contours, key = cv2.contourArea, reverse = True)[i]

        area = cv2.contourArea(sel_cnts)

        if area < 1000:
            continue

        # get orientation angle and center coord
        center, axis,angle = cv2.fitEllipse(sel_cnts)

        hyp = 100  # length of the orientation line

        # Find out coordinates of 2nd point if given length of line and center coord 
        linex = int(center[0]) + int(math.sin(math.radians(angle))*hyp)
        liney = int(center[1]) - int(math.cos(math.radians(angle))*hyp)

        # Draw orienation
        cv2.line(img, (int(center[0]),int(center[1])), (linex, liney), (0,0,255),5)             
        cv2.circle(img, (int(center[0]), int(center[1])), 10, (255,0,0), -1)

    return img

def filtering(img, imgray, mode):
    imgray = cv2.medianBlur(imgray, 11)
    thresh = cv2.Canny(imgray,75,200)

    return thresh, imgray

Does anyone know what the problem is? Anyone know how I can improve this script?

Upvotes: 2

Views: 6137

Answers (2)

Jeru Luke
Jeru Luke

Reputation: 21203

  1. I have a suggestion. Since you have extracted each of the object in the image as a contour, try fitting an ellipse to each of them.

  2. Then find the major axis of each of the ellipse.

  3. Now find the angle of orientation of these major axis.

Upvotes: 1

RevJohn
RevJohn

Reputation: 1074

The shape that has not been detected is too close to the black background and as such its contour has been merged with the contour of the white object area. The second orientation you find in one of the objects is in fact the orientation of the outer contour. To circumvent some of this you can dilate or close the binary image after thresholding using the cv2.dilate function from: cv2.dilate.

Upvotes: 2

Related Questions