Skip to content

Commit

Permalink
support RotatedRect
Browse files Browse the repository at this point in the history
  • Loading branch information
mohawk2 committed Mar 23, 2023
1 parent 0d28714 commit 91e0abf
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 2 deletions.
41 changes: 41 additions & 0 deletions Imgproc/funclist.pl
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,47 @@
@param offset Optional offset by which every contour point is shifted. This is useful if the
contours are extracted from the image ROI and then they should be analyzed in the whole image
context.',0,'void',['Mat','image','',[]],['vector_Mat','contours','',['/O']],['Mat','hierarchy','',['/O']],['int','mode','',[]],['int','method','',[]],['Point','offset','Point()',[]]],
['','fitEllipseDirect','@brief Fits an ellipse around a set of 2D points.
The function calculates the ellipse that fits a set of 2D points.
It returns the rotated rectangle in which the ellipse is inscribed.
The Direct least square (Direct) method by @cite Fitzgibbon1999 is used.
For an ellipse, this basis set is \\f$ \\chi= \\left(x^2, x y, y^2, x, y, 1\\right) \\f$,
which is a set of six free coefficients \\f$ A^T=\\left\\{A_{\\text{xx}},A_{\\text{xy}},A_{\\text{yy}},A_x,A_y,A_0\\right\\} \\f$.
However, to specify an ellipse, all that is needed is five numbers; the major and minor axes lengths \\f$ (a,b) \\f$,
the position \\f$ (x_0,y_0) \\f$, and the orientation \\f$ \\theta \\f$. This is because the basis set includes lines,
quadratics, parabolic and hyperbolic functions as well as elliptical functions as possible fits.
The Direct method confines the fit to ellipses by ensuring that \\f$ 4 A_{xx} A_{yy}- A_{xy}^2 > 0 \\f$.
The condition imposed is that \\f$ 4 A_{xx} A_{yy}- A_{xy}^2=1 \\f$ which satisfies the inequality
and as the coefficients can be arbitrarily scaled is not overly restrictive.
\\f{equation*}{
\\epsilon ^2= A^T D^T D A \\quad \\text{with} \\quad A^T C A =1 \\quad \\text{and} \\quad C=\\left(\\begin{matrix}
0 & 0 & 2 & 0 & 0 & 0 \\\\
0 & -1 & 0 & 0 & 0 & 0 \\\\
2 & 0 & 0 & 0 & 0 & 0 \\\\
0 & 0 & 0 & 0 & 0 & 0 \\\\
0 & 0 & 0 & 0 & 0 & 0 \\\\
0 & 0 & 0 & 0 & 0 & 0
\\end{matrix} \\right)
\\f}
The minimum cost is found by solving the generalized eigenvalue problem.
\\f{equation*}{
D^T D A = \\lambda \\left( C\\right) A
\\f}
The system produces only one positive eigenvalue \\f$ \\lambda\\f$ which is chosen as the solution
with its eigenvector \\f$\\mathbf{u}\\f$. These are used to find the coefficients
\\f{equation*}{
A = \\sqrt{\\frac{1}{\\mathbf{u}^T C \\mathbf{u}}} \\mathbf{u}
\\f}
The scaling factor guarantees that \\f$A^T C A =1\\f$.
@param points Input 2D point set, stored in std::vector\\<\\> or Mat',0,'RotatedRect',['Mat','points','',[]]],
['','rectangle','@brief Draws a simple, thick, or filled up-right rectangle.
The function cv::rectangle draws a rectangle outline or a filled rectangle whose two opposite corners
Expand Down
14 changes: 14 additions & 0 deletions classes.pl
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
(
['RotatedRect',[],'@brief The class represents rotated (i.e. not up-right) rectangles on a plane.
Each rectangle is specified by the center point (mass center), length of each side (represented by
#Size2f structure) and the rotation angle in degrees.
The sample below demonstrates how to use RotatedRect:
@snippet snippets/core_various.cpp RotatedRect_demo
![image](pics/rotatedrect.png)
@sa CamShift, fitEllipse, minAreaRect, CvBox2D',0,'cv::RotatedRect',[[[],''],[[['Point2f','center','',['/C','/Ref']],['Size2f','size','',['/C','/Ref']],['float','angle','',[]]],'full constructor
@param center The rectangle mass center.
@param size Width and height of the rectangle.
@param angle The rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc.,
the rectangle becomes an up-right rectangle.']]],
['KeyPoint',[],'@brief Data structure for salient point detectors.
The class instance stores a keypoint, i.e. a point feature found by one of many available keypoint
Expand Down
2 changes: 2 additions & 0 deletions funclist.pl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
(
['RotatedRect','boundingRect','returns 4 vertices of the rectangle
@param pts The points array for storing rectangle vertices. The order is bottomLeft, topLeft, topRight, bottomRight.',1,'Rect'],
['KeyPoint','convert','This method converts vector of keypoints to vector of points or the reverse, where each keypoint is
assigned the same size and the same orientation.
Expand Down
1 change: 1 addition & 0 deletions genpp.pl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ package PP::OpenCV;
Rect=>[map ['ptrdiff_t', $_], qw(x y width height)],
Scalar=>[map ['double', "v$_", "val[$_]"], 0..3],
Size=>[map ['ptrdiff_t', $_], qw(width height)],
Size2f=>[map ['float', $_], qw(width height)],
Vec4f=>[map ['float', "v$_", "val[$_]"], 0..3],
Vec6f=>[map ['float', "v$_", "val[$_]"], 0..5],
);
Expand Down
26 changes: 24 additions & 2 deletions maint/genlists
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use warnings;
use JSON::PP;
use File::Basename;
use File::Spec::Functions;
use File::Temp qw(tempdir);
use File::Path qw(make_path);
use File::Basename qw(dirname);
use Cwd;
use IPC::Open2;
use Data::Dumper;
Expand All @@ -21,12 +24,28 @@ EOF
my @HEADERS_FILES = do { local @ARGV = $HEADERS; grep !/^\s*#/, <> };
chomp @HEADERS_FILES;

my $tdir = tempdir(CLEANUP=>1);
sub process_header {
my ($dir, $file) = @_;
open my $fh, '<', catfile($dir, $file) or die "$file: $!";
my $outfile = catfile($tdir, $file);
my $outdir = dirname $outfile;
make_path $outdir or die "$outdir: $!" if !-d $outdir;
open my $outfh, '>', $outfile or die "$outfile: $!";
my $intext = do { local $/; <$fh> };
$intext =~ s/(class\s+)(CV_EXPORTS)(\s+RotatedRect)/$1${2}_W$3/;
$intext =~ s/^(\s*)(RotatedRect\((?:.*angle|\)))/${1}CV_WRAP $2/gm;
$intext =~ s/^(\s*)(.*?boundingRect\()/${1}CV_WRAP $2/m;
print $outfh $intext;
$outfile;
}

my $json_data;
{
my $old_dir = getcwd();
chdir $CVDIR or die "chdir: $!";
my $pid = open2(my $child_out, my $child_in, qw(python3 -c), $PYSCRIPT);
print $child_in map catfile($HEADERS_DIR, $_)."\n", @HEADERS_FILES;
print $child_in map process_header($HEADERS_DIR, $_)."\n", @HEADERS_FILES;
close $child_in;
$json_data = decode_json do { local $/; <$child_out> };
chdir $old_dir or die "chdir: $!";
Expand All @@ -45,11 +64,13 @@ my %force = map +($_=>1), qw(
cv.FileStorage.operator[]
cv.KeyPoint.overlap
cv.KeyPoint.convert
cv.RotatedRect.boundingRect
cv.cvtColor
cv.rectangle
cv.ellipse2Poly
cv.getAffineTransform
cv.getGaborKernel
cv.fitEllipseDirect
cv.drawContours
cv.findContours
cv.threshold
Expand Down Expand Up @@ -98,8 +119,9 @@ my %class = map +($_=>1), qw(
CascadeClassifier Subdiv2D TrackerKCF TrackerCSRT TrackerMIL
FileNode FileStorage DMatch KeyPoint Algorithm CLAHE GeneralizedHough
HOGDescriptor SparsePyrLKOpticalFlow DISOpticalFlow SparseOpticalFlow
TermCriteria RNG RotatedRect
);
my $no_want = qr/^(TermCriteria|RNG|RotatedRect)/;
my $no_want = qr/^(TermCriteria|RNG)/;
my $skip_re = join '|',
qr/^cv\.ipp/,
qr/^cv\.moments/,
Expand Down
1 change: 1 addition & 0 deletions typemap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ vector_KeyPointWrapper* T_OPENCV_VECTOR
vector_MatWrapper* T_OPENCV_VECTOR
vector_StringWrapper* T_OPENCV_VECTOR
vector_vector_Point2fWrapper* T_OPENCV_VECTOR
RotatedRectWrapper* T_PTROBJ_SPECIAL
KeyPointWrapper* T_PTROBJ_SPECIAL
DMatchWrapper* T_PTROBJ_SPECIAL
FileStorageWrapper* T_PTROBJ_SPECIAL
Expand Down

0 comments on commit 91e0abf

Please sign in to comment.