Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/shape/src/aff_trans.cpp
16337 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "precomp.hpp"
44
45
namespace cv
46
{
47
48
class AffineTransformerImpl : public AffineTransformer
49
{
50
public:
51
/* Constructors */
52
AffineTransformerImpl()
53
{
54
fullAffine = true;
55
name_ = "ShapeTransformer.AFF";
56
transformCost = 0;
57
}
58
59
AffineTransformerImpl(bool _fullAffine)
60
{
61
fullAffine = _fullAffine;
62
name_ = "ShapeTransformer.AFF";
63
transformCost = 0;
64
}
65
66
/* Destructor */
67
~AffineTransformerImpl()
68
{
69
}
70
71
//! the main operator
72
virtual void estimateTransformation(InputArray transformingShape, InputArray targetShape, std::vector<DMatch> &matches) CV_OVERRIDE;
73
virtual float applyTransformation(InputArray input, OutputArray output=noArray()) CV_OVERRIDE;
74
virtual void warpImage(InputArray transformingImage, OutputArray output,
75
int flags, int borderMode, const Scalar& borderValue) const CV_OVERRIDE;
76
77
//! Setters/Getters
78
virtual void setFullAffine(bool _fullAffine) CV_OVERRIDE {fullAffine=_fullAffine;}
79
virtual bool getFullAffine() const CV_OVERRIDE {return fullAffine;}
80
81
//! write/read
82
virtual void write(FileStorage& fs) const CV_OVERRIDE
83
{
84
writeFormat(fs);
85
fs << "name" << name_
86
<< "affine_type" << int(fullAffine);
87
}
88
89
virtual void read(const FileNode& fn) CV_OVERRIDE
90
{
91
CV_Assert( (String)fn["name"] == name_ );
92
fullAffine = int(fn["affine_type"])?true:false;
93
}
94
95
private:
96
bool fullAffine;
97
Mat affineMat;
98
float transformCost;
99
100
protected:
101
String name_;
102
};
103
104
void AffineTransformerImpl::warpImage(InputArray transformingImage, OutputArray output,
105
int flags, int borderMode, const Scalar& borderValue) const
106
{
107
CV_INSTRUMENT_REGION();
108
109
CV_Assert(!affineMat.empty());
110
warpAffine(transformingImage, output, affineMat, transformingImage.getMat().size(), flags, borderMode, borderValue);
111
}
112
113
114
static Mat _localAffineEstimate(const std::vector<Point2f>& shape1, const std::vector<Point2f>& shape2,
115
bool fullAfine)
116
{
117
Mat out(2,3,CV_32F);
118
int siz=2*(int)shape1.size();
119
120
if (fullAfine)
121
{
122
Mat matM(siz, 6, CV_32F);
123
Mat matP(siz,1,CV_32F);
124
int contPt=0;
125
for (int ii=0; ii<siz; ii++)
126
{
127
Mat therow = Mat::zeros(1,6,CV_32F);
128
if (ii%2==0)
129
{
130
therow.at<float>(0,0)=shape1[contPt].x;
131
therow.at<float>(0,1)=shape1[contPt].y;
132
therow.at<float>(0,2)=1;
133
therow.row(0).copyTo(matM.row(ii));
134
matP.at<float>(ii,0) = shape2[contPt].x;
135
}
136
else
137
{
138
therow.at<float>(0,3)=shape1[contPt].x;
139
therow.at<float>(0,4)=shape1[contPt].y;
140
therow.at<float>(0,5)=1;
141
therow.row(0).copyTo(matM.row(ii));
142
matP.at<float>(ii,0) = shape2[contPt].y;
143
contPt++;
144
}
145
}
146
Mat sol;
147
solve(matM, matP, sol, DECOMP_SVD);
148
out = sol.reshape(0,2);
149
}
150
else
151
{
152
Mat matM(siz, 4, CV_32F);
153
Mat matP(siz,1,CV_32F);
154
int contPt=0;
155
for (int ii=0; ii<siz; ii++)
156
{
157
Mat therow = Mat::zeros(1,4,CV_32F);
158
if (ii%2==0)
159
{
160
therow.at<float>(0,0)=shape1[contPt].x;
161
therow.at<float>(0,1)=shape1[contPt].y;
162
therow.at<float>(0,2)=1;
163
therow.row(0).copyTo(matM.row(ii));
164
matP.at<float>(ii,0) = shape2[contPt].x;
165
}
166
else
167
{
168
therow.at<float>(0,0)=shape1[contPt].y;
169
therow.at<float>(0,1)=-shape1[contPt].x;
170
therow.at<float>(0,3)=1;
171
therow.row(0).copyTo(matM.row(ii));
172
matP.at<float>(ii,0) = shape2[contPt].y;
173
contPt++;
174
}
175
}
176
Mat sol;
177
solve(matM, matP, sol, DECOMP_SVD);
178
out.at<float>(0,0)=sol.at<float>(0,0);
179
out.at<float>(0,1)=sol.at<float>(1,0);
180
out.at<float>(0,2)=sol.at<float>(2,0);
181
out.at<float>(1,0)=-sol.at<float>(1,0);
182
out.at<float>(1,1)=sol.at<float>(0,0);
183
out.at<float>(1,2)=sol.at<float>(3,0);
184
}
185
return out;
186
}
187
188
void AffineTransformerImpl::estimateTransformation(InputArray _pts1, InputArray _pts2, std::vector<DMatch>& _matches)
189
{
190
CV_INSTRUMENT_REGION();
191
192
Mat pts1 = _pts1.getMat();
193
Mat pts2 = _pts2.getMat();
194
CV_Assert((pts1.channels()==2) && (pts1.cols>0) && (pts2.channels()==2) && (pts2.cols>0));
195
CV_Assert(_matches.size()>1);
196
197
if (pts1.type() != CV_32F)
198
pts1.convertTo(pts1, CV_32F);
199
if (pts2.type() != CV_32F)
200
pts2.convertTo(pts2, CV_32F);
201
202
// Use only valid matchings //
203
std::vector<DMatch> matches;
204
for (size_t i=0; i<_matches.size(); i++)
205
{
206
if (_matches[i].queryIdx<pts1.cols &&
207
_matches[i].trainIdx<pts2.cols)
208
{
209
matches.push_back(_matches[i]);
210
}
211
}
212
213
// Organizing the correspondent points in vector style //
214
std::vector<Point2f> shape1; // transforming shape
215
std::vector<Point2f> shape2; // target shape
216
for (size_t i=0; i<matches.size(); i++)
217
{
218
Point2f pt1=pts1.at<Point2f>(0,matches[i].queryIdx);
219
shape1.push_back(pt1);
220
221
Point2f pt2=pts2.at<Point2f>(0,matches[i].trainIdx);
222
shape2.push_back(pt2);
223
}
224
225
Mat affine;
226
if (fullAffine)
227
{
228
estimateAffine2D(shape1, shape2).convertTo(affine, CV_32F);
229
} else
230
{
231
estimateAffinePartial2D(shape1, shape2).convertTo(affine, CV_32F);
232
}
233
234
if (affine.empty())
235
//In case there is not good solution, just give a LLS based one
236
affine = _localAffineEstimate(shape1, shape2, fullAffine);
237
238
affineMat = affine;
239
}
240
241
float AffineTransformerImpl::applyTransformation(InputArray inPts, OutputArray outPts)
242
{
243
CV_INSTRUMENT_REGION();
244
245
Mat pts1 = inPts.getMat();
246
CV_Assert((pts1.channels()==2) && (pts1.cols>0));
247
248
//Apply transformation in the complete set of points
249
Mat fAffine;
250
transform(pts1, fAffine, affineMat);
251
252
// Ensambling output //
253
if (outPts.needed())
254
{
255
outPts.create(1,fAffine.cols, CV_32FC2);
256
Mat outMat = outPts.getMat();
257
for (int i=0; i<fAffine.cols; i++)
258
outMat.at<Point2f>(0,i)=fAffine.at<Point2f>(0,i);
259
}
260
261
// Updating Transform Cost //
262
Mat Af(2, 2, CV_32F);
263
Af.at<float>(0,0)=affineMat.at<float>(0,0);
264
Af.at<float>(0,1)=affineMat.at<float>(1,0);
265
Af.at<float>(1,0)=affineMat.at<float>(0,1);
266
Af.at<float>(1,1)=affineMat.at<float>(1,1);
267
SVD mysvd(Af, SVD::NO_UV);
268
Mat singVals=mysvd.w;
269
transformCost=std::log((singVals.at<float>(0,0)+FLT_MIN)/(singVals.at<float>(1,0)+FLT_MIN));
270
271
return transformCost;
272
}
273
274
Ptr <AffineTransformer> createAffineTransformer(bool fullAffine)
275
{
276
return Ptr<AffineTransformer>( new AffineTransformerImpl(fullAffine) );
277
}
278
279
} // cv
280
281