Ask Your Question

read arrow orientation from image

asked 2016-12-09 04:19:00 -0600

jaka87 gravatar image

updated 2016-12-12 01:40:40 -0600

Hello. I created script to get arrows from the image. Im trying to detect orientation for each arrow. With my script i manage to get somewhat accurate results. The problem is that Im getting same results if arrows are oriented up or down, to the left or to the right. How to know if the arrow is pointing to left or to the right? In both cases of the pictures below i get same result around 90 deg.

image description image description

original image

image description

UPDATE 12.12.2016: i manage to get it somewhat working by blurring the picture more to get better contour. I then create bounding rectangle and split it in two parts and calculate surface area of each to get if arrows are facing up or down. Then I chose two points on bounding rectangle and calculate degrees from it. From degrees i then get wind direction.

Now bounding rectangle can sometimes be strangely oriented and giving slightly wrong directions. I think bounding ellipse is more appropriate but the results of degrees are not always correct since i cant set in which direction to check for the angle like i did in rectangle. How could i do the same with ellipse or just mathematically invert degree value based on arrow direction ?

import cv2
import numpy as np
from matplotlib import pyplot as plt
import math
import matplotlib.path as mplPath
from math import atan2, degrees, pi

def direction2(img):

    height, width, channels = img.shape 
    img = cv2.resize(img, (width*8, height*8))                    
    img = cv2.medianBlur(img,9)
    imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    ret,th1 = cv2.threshold(imgray,150,255,cv2.THRESH_BINARY)
    #return edged

    (img2,cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


    for c in cnts:
        area = cv2.contourArea(c)
        #print area
        if area > 500 and area < 1650:  
            (x,y),radius = cv2.minEnclosingCircle(c)
            center = (int(x),int(y))

            ellipse = cv2.fitEllipse(c)
            (x,y),(MA,ma),angle = cv2.fitEllipse(c)

            rect = cv2.minAreaRect(c)
            box = cv2.boxPoints(rect)
            box = np.int0(box)
            #print box

            a= math.hypot(box[1][0] - box[0][0], box[1][1] - box[0][1])
            b= math.hypot(box[3][0] - box[0][0], box[3][1] - box[0][1])

            if a>b: 


                bbPath = mplPath.Path(np.array([[box[0][0], box[0][1]],[xos, yos],[xos2, yos2],[box[3 ...
edit retag flag offensive close merge delete


You might try template matching (if the size and orientation of the arrows is constant) or corner detection using a Harris detector...

kbarni gravatar imagekbarni ( 2016-12-09 06:09:15 -0600 )edit

i tried template matching with so so results. With the script above the shape is detected just fine. I think it would solve my problem if i would draw bowning rectangle around arrow, split it to two sides by width and then calculate how which one is more filled with contour. The only problem is i don't know how to do it.

jaka87 gravatar imagejaka87 ( 2016-12-09 13:43:30 -0600 )edit

Can you share the original Image without any of your marking's?

Balaji R gravatar imageBalaji R ( 2016-12-11 20:23:14 -0600 )edit

I updated the question.

jaka87 gravatar imagejaka87 ( 2016-12-12 01:41:48 -0600 )edit

It looks like arrow on a map. I think you should try @kbarni answer but with differents template (0 45,90°...). You can try fourier-mellin transform (not included in opencv) too

LBerger gravatar imageLBerger ( 2016-12-12 02:06:14 -0600 )edit

1 answer

Sort by » oldest newest most voted

answered 2016-12-09 13:42:30 -0600

Tetragramm gravatar image

I think moments are the most useful tool here. Take two moments, that of the outline you have in yellow (just the outline) and the image inside the box that contains the outline. The central moments of the outline is the geometric center of the arrow, more or less. The central moments of the image around the outline is concentrated (because things besides black is what it's measuring) at the tail of the arrow.

Draw a line from the tail point you found through the center point you found, and there you are, a direction.

No promises though. Your edges are really fuzzy, which is throwing off the contours. Think you can fix that?

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2016-12-09 04:19:00 -0600

Seen: 4,859 times

Last updated: Dec 12 '16