# How to find the rotated angle of object

I am using the homographythis tutorial for pattern matching. It is working but i need to find the degree of rotation of that object in scene. See the template image and scene image with output . I need to find the angle based on template.

edit retag close merge delete

What do you mean by rotation? in plan (which one?), in space?

( 2015-10-30 03:11:07 -0500 )edit

Ok. I am having two images one is template and another is scene which captured from webcam. While i am doing the surf detection it finds the match. but i need to detect the angle of rotation in the scene with respect to the template

( 2015-10-30 03:50:30 -0500 )edit
1

So, I am asking you again, what angle do you need: in the plane of the photo?

( 2015-10-30 06:21:13 -0500 )edit

See the template image and scene image with output . I need
to find the angle based on template.

( 2015-10-30 09:19:46 -0500 )edit
2

so, you got the homography matrix, and can apply Rodrigues() on it, to get the euler angles.

but think of it, there will be 3 angles involved, not one.

( 2015-11-01 01:09:37 -0500 )edit

I'm pretty new on openCV and I'm using python, does anyone have a python syntax for it?

( 2020-08-20 05:25:58 -0500 )edit
( 2020-08-22 09:28:04 -0500 )edit

Sort by ยป oldest newest most voted

I have changed your image to write my program because i don't need rectangle. only shape object is needed.

Image is

program is based on this paper (appendix)

#include <opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>

using namespace cv;
using namespace std;
class MatchDescriptor {
public :
vector<Point2d> sContour;
vector<complex<float> > b;
vector<complex<float> > a;
vector<float> frequence;
vector<float> rho,psi;
double pi;
int nbDesFit;

public :
MatchDescriptor(){nbDesFit=7;pi=acos(-1.0);};;
float AjustementRtSafe(vector<Point2d> &c,float &alphaMin,float &phiMin,float &sMin);
float Ajustement(vector<Point2d> &c,float &alphaMin,float &phiMin,float &sMin);
void falpha(float x,float *fn,float *df);
void InitFrequence();
float rtsafe(float x1,float x2,float xacc);
float Distance(complex<float> r,float alpha)
{
long            i;
complex<float>      j(0,1);
float       d=0;

for (i=1;i<=nbDesFit;i++)
{
d += abs(a[i]-b[i]*r*exp(j*float(alpha*frequence[i])))+ abs(a[a.size()-i]-b[a.size()-i]*r*exp(j*float(alpha*frequence[a.size()-i])));
}
return d;
};

};

void MatchDescriptor::InitFrequence()
{
long i;
int nbElt=sContour.size();
frequence.resize(sContour.size());

for (i=0;i<=nbElt/2;i++)
frequence[i] = 2*pi*(float)i/nbElt;
for (i=nbElt/2+1;i<nbElt;i++)
frequence[i] = 2*pi*(float)(i-nbElt)/nbElt;
}

void MatchDescriptor::falpha(float x,float *fn,float *df)
{
long    n,nbElt = sContour.size();
float   s1=0,s2=0,s3=0,s4=0;
float   ds1=0,ds2=0,ds3=0,ds4=0;

for (n=1;n<=nbDesFit;n++)
{
s1 +=   rho[n] * sin(psi[n]+frequence[n]*x) +
rho[nbElt-n] * sin(psi[nbElt-n]+frequence[nbElt-n]*x);
s2 +=   frequence[n] * rho[n] * cos(psi[n]+frequence[n]*x) +
frequence[nbElt-n] * rho[nbElt-n] * cos(psi[nbElt-n]+frequence[nbElt-n]*x);
s3 +=   rho[n] * cos(psi[n]+frequence[n]*x) +
rho[nbElt-n] * cos(psi[nbElt-n]+frequence[nbElt-n]*x);
s4 +=   frequence[n] * rho[n] * sin(psi[n]+frequence[n]*x) +
frequence[nbElt-n] * rho[nbElt-n] * sin(psi[nbElt-n]+frequence[nbElt-n]*x);
ds1 +=  frequence[n]*rho[n] * cos(psi[n]+frequence[n]*x) +
frequence[nbElt-n]*rho[nbElt-n] * cos(psi[nbElt-n]+frequence[nbElt-n]*x);
ds2 +=  -frequence[n]*frequence[n] * rho[n] * sin(psi[n]+frequence[n]*x) -
frequence[nbElt-n]*frequence[nbElt-n] * rho[nbElt-n] * sin(psi[nbElt-n]+frequence[nbElt-n]*x);
ds3 +=  -frequence[n]*rho[n] * sin(psi[n]+frequence[n]*x) -
frequence[nbElt-n]*rho[nbElt-n] * sin(psi[nbElt-n]+frequence[nbElt-n]*x);
ds4 +=  frequence[n]*frequence[n] * rho[n] * cos(psi[n]+frequence[n]*x) +
frequence[nbElt-n]*frequence[nbElt-n] * rho[nbElt-n] * cos(psi[nbElt-n]+frequence[nbElt-n]*x);
}
*fn = s1 * s2 - s3 *s4;
*df = ds1 * s2 + s1 * ds2 - ds3 * s4 -  s3 * ds4;
}

float MatchDescriptor::AjustementRtSafe(vector<Point2d> &c,float &alphaMin,float &phiMin,float &sMin)
{
long            n,nbElt = sContour.size();
float           s1,s2,sign1,sign2,df,x1=nbElt,x2=nbElt,dx;
float           dist,distMin = 10000,alpha,s,phi;
complex<float>  j(0,1),zz;

InitFrequence();
rho.resize(nbElt);
psi.resize(nbElt);

b.resize(nbElt ...
more

Nice code @LBerger. Thank you for posting it !

PS:

• the line: alpha = alpha; (should be line 131)
• I had to explicitly cast to double the line: Point2d p = Point2d(c[i % c.size()]) + d * (s - l1) / (l2 - l1); but I think that it is because I use an old version of OpenCV (2.4.9)
( 2015-11-07 15:01:28 -0500 )edit

thanks @Eduardo I have comment line alpha and I use VS2013 with opencv 3.0 i have posted this code with many compilers warnnings

I must say that AjustementRtSafe is a numercial recipes function to solve an equation using a newton raphson method

( 2015-11-07 15:22:20 -0500 )edit

happy to know that's somebody use this code.

MAXIT : as it is written some code i have used come from NRC. That's case here see page 366.

nbDesFit : a contour of N point give you N terms in FFT. if you want to fit two curves (shapes) very often you don't need N terms nbDesFit is enough. Example 512 points give you 512 terms in FFT and to fit with other shapes very often 5 terms in FFT give you a very good fit.

becarefull a contour x is a complex signal not a real signal. Hence in FFT X of x X(n)<>conjugate(X(-n))

( 2016-02-15 02:20:07 -0500 )edit

The link of the paper is down , here it's the name of the paper "Shape Discrimination Using Fourier Descrptors" by ERIC PERSOON, and others , and here its another link Paper link

( 2016-03-22 11:15:39 -0500 )edit

What does the following line perform? vector<point2d> c = ReSampleContour(contours[ctrSelec[i]],1024); Why 1024? Has anyone understood it?

( 2016-04-04 01:04:32 -0500 )edit

To match contour using fourier descriptors all contours must have same number of points. You can choose 1024 or any values. This value musn't destroy your shape...(At the end your contour will have N points)

( 2016-04-04 01:56:34 -0500 )edit

What should be taken into consideration while choosing a value? Why have u chosen 1024, was it derived by experimental result? And where do u get the fourier descriptors in the code above? Have u made them scale and starting point invariant? If yes where?

( 2016-04-04 02:20:15 -0500 )edit

Fourier descriptor :dft(z[i],Z[i],DFT_SCALE|DFT_REAL_OUTPUT);

Program results are scale, rotation and phase shift to apply to each contour to have best match between contour( least square methods)

( 2016-04-04 02:26:15 -0500 )edit

I dnt nid fourier descriptor which are rotational invariant they just need to be translation and scale invariant. It means that u have 1024 fourier descriptors

( 2016-04-04 02:37:51 -0500 )edit

I have read quickly your link. Program try to find transformation (translation scale and rotation) minimizing least square error. It is not like in your link. I think there a database of traffic sign using fourier descriptor with . zero dc-component and fixed energy and used algorithm in described p27-29.

( 2016-05-28 05:07:26 -0500 )edit

Official site

GitHub

Wiki

Documentation