How to find the rotated angle of object?

@laurent.berger Thanks for the code! I am currently using it for one of my projects and was wondering in the equations you supplied at the end, why is the boundary for the second equation p=-N/2 to N/2-1. It is my understanding that this is the forward FT, so shouldn’t it be from 0 to N? Thanks!

https://answers.opencv.org/question/74712/how-to-find-the-rotated-angle-of-object/

1 Like

Hi,
this code is now in opencv_contrib
Discrete Fourier transform is a periodic function (period = N)

1 Like

Hi, would you be kindly willing to have a quick zoom meeting to discuss the code in more detail? I am new to image processing and a bit lost trying to figure out what each function does

You should first read a math book about fourier and dft transform and read papers in bibliography
E Persoon and King-Sun Fu. Shape discrimination using fourier descriptors. IEEE Transactions on Pattern Analysis and Machine Intelligence , 7(3):170–179, 1977.
L Berger, V A Raghunathan, C Launay, D Ausserré, and Y Gallot. Coalescence in 2 dimensions: experiments on thin copolymer films and numerical simulations. The European Physical Journal B - Condensed Matter and Complex Systems , 2(1):93–99, 1998.

and http://www.numerical.recipes/

a tutorial or some explanation of that module would be helpful. the docs so far only present the APIs, but not what their purpose is, or how to use/combine them.

the issue isn’t understanding the (discrete) fourier transform but what it is doing here specifically. it’s insufficient to merely point at references to scientific publications from 1977 that aren’t even hyperlinks. this is not a scientific paper, it’s a software library. it’s engineering.

personally, I’m always thrilled to see some illustrations. illustrations are a good idea in most cases because they are more precise than paragraphs of words.

thank you for your contribution.

3 Likes

there is two samples

and there is this too

Repository for OpenCV’s extra modules

This repository is intended for the development of so-called “extra” modules, contributed functionality. New modules quite often do not have stable API, and they are not well-tested. Thus, they shouldn’t be released as a part of official OpenCV distribution, since the library maintains binary compatibility, and tries to provide decent performance and stability.

So, all the new modules should be developed separately, and published in the opencv_contrib repository at first. Later, when the module matures and gains popularity, it is moved to the central OpenCV repository, and the development team provides production-quality support for this module.

Really your comment is too funny :grin:

Thanks for the resources, they’re much appreciated. I have modified the original code using some of the functions but I run into two problems. Firstly, when estimateTransformation() is comparing a contour with itself, it evaluation the rotation as -180 degrees. Secondly, I can only get 1 of the rotated contours drawn, the second one doesn’t appear. Would appreciate your input!

Here is the code:

int main(int argc, char **argv)
{
vector<vector> contours;
vector hierarchy;
Mat mTest,mThresh,mConnected;

Mat m1,m2,m3,m4,m5;
Mat m = imread("/Users/Memo/Desktop/image.jpg", IMREAD_GRAYSCALE);

bitwise_not(m,m1);
threshold(m1,mThresh,5,255,THRESH_BINARY);
findContours(mThresh,contours,hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
vector<int> ctrSelec;
for (int i = 0; i < contours.size(); i++)
{
    if (contours[i].size()>= 500 )
    {
        ctrSelec.push_back(i);
    }
}

Mat mc = Mat::zeros(m.size(),CV_8UC3);

vector< vector<Point2f> >z;
vector< vector<Point2f> >Z;
z.resize(ctrSelec.size());
Z.resize(ctrSelec.size());


for (int i = 0; i < ctrSelec.size();i++)
{
    ximgproc::contourSampling(contours[ctrSelec[i]], z[i], 1024);
    dft(z[i],Z[i],DFT_SCALE); //Fourier transform
}

int indRef = 1;
vector<float> alpha,phi,s;
alpha.resize(ctrSelec.size());
phi.resize(ctrSelec.size());
s.resize(ctrSelec.size());
ximgproc::ContourFitting fit;
double dist;
Mat t;
fit.setFDSize(50);
fit.setCtrSize(1024);
Mat dst;
vector<vector<Point>> ctrRotated;

for (int i = 0; i < ctrSelec.size();i++)
{
fit.estimateTransformation(z[indRef], z[i], t, &dist, false);
cout<<“Contour “<<indRef<<” with “<<i<< " origin “<<1-t.at(0,0)<<” and rotated of”<<t.at(0, 1)* 180 / M_PI<<” and scale "<<t.at(0, 2)<<endl;

for (int i = 0; i < ctrSelec.size(); i++)
{
    if (i!=indRef)
        drawContours(mc,contours,ctrSelec[i],Scalar(255,0,0));
    else
        drawContours(mc,contours,ctrSelec[i],Scalar(255,255,255));
    putText(mc,format("%d",i),Point(Z[i][0].x,Z[i][0].y),FONT_HERSHEY_SIMPLEX,1,Scalar(255,0,0));
}

ximgproc::transformFD(z[1], t, dst, false);
cout<<"bla bla"<<endl;
ctrRotated.push_back(dst);
drawContours(mc,ctrRotated,0,Scalar(0,0,255));

// for (int i = 0; i < ctrSelec.size(); i++)
// {
// drawContours(mc,ctrRotated,i,Scalar(0,0,255));
// }
}
imshow("mc ",mc);
waitKey();
return 0;
};

Thanks for the resources, they helped a lot! I’m using the estimateTransformation() function but whenever the contour is compared with itself it yields a -180 degree rotation. Any advice on how to fix that?

Can you post binary images ?

The top and bottom contour match but when the top and top contour are input the angle of rotation is -180

With your data result is

Angle = 21.218827593401404
Scale = 0.9849248448953134

But I don’t know what you want because this two contour are not similar

Program is

import numpy as np
import cv2 as cv
import math


imgRef = cv.imread(r"C:\Users\Laurent\Desktop\ctr.jpeg")
img = cv.cvtColor(imgRef,cv.COLOR_BGR2GRAY)
img = 255 - img
ret, img_bin = cv.threshold(img,100,255,cv.THRESH_OTSU)
ctr, hiera = cv.findContours(img_bin, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE )
ctrRef = ctr[0][:,0,:]
code = 0
fit = cv.ximgproc.createContourFitting(1024,16);
# sampling contour we want 256 points
cn= np.reshape(ctrRef,[ctrRef.shape[0],1,2])

ctrRef2d = cv.ximgproc.contourSampling(cn,  256)
ctrRot2d = cv.ximgproc.contourSampling(ctr[1],  256)
fit.setFDSize(16)
c1 = ctrRef2d
c2 = ctrRot2d
alphaPhiST, dist	 = fit.estimateTransformation(ctrRot2d, ctrRef2d)
print( "Transform *********\n Origin = ", 1-alphaPhiST[0,0])

dst = cv.ximgproc.transformFD(ctrRot2d, alphaPhiST,cn, False);
ctmp= np.reshape(dst,[dst.shape[0],2])
cdst=ctmp.astype(int)

c = [ ctrRef,cdst]
cv.drawContours(imgRef, c, -1, (0,255,0),1);
cv.imshow("FD Curve matching", imgRef);
cv.waitKey()