Reputation: 2252
Hi guys,
I'm trying to figure out how to get the orientation of the arrow in the middle of the picture.
If the arrow is pointing to the north, the orientation is 0, if the arrow is pointing to the south, the orientation is pi, the first picture is 1.75 pi the second picture is 0.5 pi, the third picture is 0.75 pi.
I want the orientation to be as accurate as possible.
I've tried to go through the OpenCV library, but failed to find out a way to do it.
Can you please help?
update: I can find where the arrow is.
Upvotes: 0
Views: 346
Reputation: 3744
You will need to do some steps. First, to identify the bounding box of the arrow as you did. Second, get the coordinates of the pixels of the arrow, here I found them to have red, green and blue values over 80, you may need to inspect this for your images. Third, get the center of area of the arrow. Finally get the properties of area of the arrow Ix
, Iy
, and Ixy
, which can be used to get the angle of rotation of the arrow.
You will need to do simple modifications to this angle, if it is a negative value, add Pi to it, also you will need to get the furthest point of arrow from its center, and if it right from the centroid, the angle should be greater than Pi, otherwise it should be less than it.
int i, x, y, t;
double xc, yc, Ix, Iy, Ixy, xf, yf, d, ang;
Bitmap img = new Bitmap(path); // load only the area that contains the arrow
List<int> px, py;
px = new List<int>();
py = new List<int>();
xc = yc = Ix = Iy = Ixy = xf = yf = d = t = 0;
for (x = 0; x < img.Width; x++)
for (y = 0; y < img.Height; y++)
if (img.GetPixel(x, y).R > 80 && img.GetPixel(x, y).G > 80 && img.GetPixel(x, y).B > 80) // you will have to check this condition for your images
{
t++; // get the number of pixels of arrow
xc += x;
yc += y;
px.Add(x); // store x-coordinates of all arrow pixels
py.Add(y); // store y-coordinates of all arrow pixels
}
// get the center of area of the arrow
xc /= t;
yc /= t;
// calculate the properties of area
for (i = 0; i < t; i++)
{
if (Math.Pow(px[i] - xc, 2) + Math.Pow(py[i] - yc, 2) > d)
{
xf = px[i] - xc;
yf = py[i] - yc;
d = Math.Pow(xf, 2) + Math.Pow(yf, 2);
}
Ix += Math.Pow(py[i] - yc, 2);
Iy += Math.Pow(px[i] - xc, 2);
Ixy += (px[i] - xc) * (py[i] - yc);
}
// calculate the angel
ang = Math.Atan2(-2 * Ixy, Ix - Iy) / 2;
// correct the angle
if (ang < 0)
ang += Math.PI;
if (xf > 0 && ang < Math.PI)
ang += Math.PI;
if (xf < 0 && ang > Math.PI)
ang -= Math.PI;
I tried this on your images and got 1.769 Pi for the first one, 0.578 Pi for the second one, and 0.832 Pi for the third one.
Upvotes: 2