Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/shape/src/tps_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 ThinPlateSplineShapeTransformerImpl CV_FINAL : public ThinPlateSplineShapeTransformer
49
{
50
public:
51
/* Constructors */
52
ThinPlateSplineShapeTransformerImpl()
53
{
54
regularizationParameter=0;
55
name_ = "ShapeTransformer.TPS";
56
tpsComputed=false;
57
transformCost = 0;
58
}
59
60
ThinPlateSplineShapeTransformerImpl(double _regularizationParameter)
61
{
62
regularizationParameter=_regularizationParameter;
63
name_ = "ShapeTransformer.TPS";
64
tpsComputed=false;
65
transformCost = 0;
66
}
67
68
/* Destructor */
69
~ThinPlateSplineShapeTransformerImpl() CV_OVERRIDE
70
{
71
}
72
73
//! the main operators
74
virtual void estimateTransformation(InputArray transformingShape, InputArray targetShape, std::vector<DMatch> &matches) CV_OVERRIDE;
75
virtual float applyTransformation(InputArray inPts, OutputArray output=noArray()) CV_OVERRIDE;
76
virtual void warpImage(InputArray transformingImage, OutputArray output,
77
int flags, int borderMode, const Scalar& borderValue) const CV_OVERRIDE;
78
79
//! Setters/Getters
80
virtual void setRegularizationParameter(double _regularizationParameter) CV_OVERRIDE { regularizationParameter=_regularizationParameter; }
81
virtual double getRegularizationParameter() const CV_OVERRIDE { return regularizationParameter; }
82
83
//! write/read
84
virtual void write(FileStorage& fs) const CV_OVERRIDE
85
{
86
writeFormat(fs);
87
fs << "name" << name_
88
<< "regularization" << regularizationParameter;
89
}
90
91
virtual void read(const FileNode& fn) CV_OVERRIDE
92
{
93
CV_Assert( (String)fn["name"] == name_ );
94
regularizationParameter = (int)fn["regularization"];
95
}
96
97
private:
98
bool tpsComputed;
99
double regularizationParameter;
100
float transformCost;
101
Mat tpsParameters;
102
Mat shapeReference;
103
104
protected:
105
String name_;
106
};
107
108
static float distance(Point2f p, Point2f q)
109
{
110
Point2f diff = p - q;
111
float norma = diff.x*diff.x + diff.y*diff.y;// - 2*diff.x*diff.y;
112
if (norma<0) norma=0;
113
//else norma = std::sqrt(norma);
114
norma = norma*std::log(norma+FLT_EPSILON);
115
return norma;
116
}
117
118
static Point2f _applyTransformation(const Mat &shapeRef, const Point2f point, const Mat &tpsParameters)
119
{
120
Point2f out;
121
for (int i=0; i<2; i++)
122
{
123
float a1=tpsParameters.at<float>(tpsParameters.rows-3,i);
124
float ax=tpsParameters.at<float>(tpsParameters.rows-2,i);
125
float ay=tpsParameters.at<float>(tpsParameters.rows-1,i);
126
127
float affine=a1+ax*point.x+ay*point.y;
128
float nonrigid=0;
129
for (int j=0; j<shapeRef.rows; j++)
130
{
131
nonrigid+=tpsParameters.at<float>(j,i)*
132
distance(Point2f(shapeRef.at<float>(j,0),shapeRef.at<float>(j,1)),
133
point);
134
}
135
if (i==0)
136
{
137
out.x=affine+nonrigid;
138
}
139
if (i==1)
140
{
141
out.y=affine+nonrigid;
142
}
143
}
144
return out;
145
}
146
147
/* public methods */
148
void ThinPlateSplineShapeTransformerImpl::warpImage(InputArray transformingImage, OutputArray output,
149
int flags, int borderMode, const Scalar& borderValue) const
150
{
151
CV_INSTRUMENT_REGION();
152
153
CV_Assert(tpsComputed==true);
154
155
Mat theinput = transformingImage.getMat();
156
Mat mapX(theinput.rows, theinput.cols, CV_32FC1);
157
Mat mapY(theinput.rows, theinput.cols, CV_32FC1);
158
159
for (int row = 0; row < theinput.rows; row++)
160
{
161
for (int col = 0; col < theinput.cols; col++)
162
{
163
Point2f pt = _applyTransformation(shapeReference, Point2f(float(col), float(row)), tpsParameters);
164
mapX.at<float>(row, col) = pt.x;
165
mapY.at<float>(row, col) = pt.y;
166
}
167
}
168
remap(transformingImage, output, mapX, mapY, flags, borderMode, borderValue);
169
}
170
171
float ThinPlateSplineShapeTransformerImpl::applyTransformation(InputArray inPts, OutputArray outPts)
172
{
173
CV_INSTRUMENT_REGION();
174
175
CV_Assert(tpsComputed);
176
Mat pts1 = inPts.getMat();
177
CV_Assert((pts1.channels()==2) && (pts1.cols>0));
178
179
//Apply transformation in the complete set of points
180
// Ensambling output //
181
if (outPts.needed())
182
{
183
outPts.create(1,pts1.cols, CV_32FC2);
184
Mat outMat = outPts.getMat();
185
for (int i=0; i<pts1.cols; i++)
186
{
187
Point2f pt=pts1.at<Point2f>(0,i);
188
outMat.at<Point2f>(0,i)=_applyTransformation(shapeReference, pt, tpsParameters);
189
}
190
}
191
192
return transformCost;
193
}
194
195
void ThinPlateSplineShapeTransformerImpl::estimateTransformation(InputArray _pts1, InputArray _pts2,
196
std::vector<DMatch>& _matches )
197
{
198
CV_INSTRUMENT_REGION();
199
200
Mat pts1 = _pts1.getMat();
201
Mat pts2 = _pts2.getMat();
202
CV_Assert((pts1.channels()==2) && (pts1.cols>0) && (pts2.channels()==2) && (pts2.cols>0));
203
CV_Assert(_matches.size()>1);
204
205
if (pts1.type() != CV_32F)
206
pts1.convertTo(pts1, CV_32F);
207
if (pts2.type() != CV_32F)
208
pts2.convertTo(pts2, CV_32F);
209
210
// Use only valid matchings //
211
std::vector<DMatch> matches;
212
for (size_t i=0; i<_matches.size(); i++)
213
{
214
if (_matches[i].queryIdx<pts1.cols &&
215
_matches[i].trainIdx<pts2.cols)
216
{
217
matches.push_back(_matches[i]);
218
}
219
}
220
221
// Organizing the correspondent points in matrix style //
222
Mat shape1((int)matches.size(),2,CV_32F); // transforming shape
223
Mat shape2((int)matches.size(),2,CV_32F); // target shape
224
for (int i=0, end = (int)matches.size(); i<end; i++)
225
{
226
Point2f pt1=pts1.at<Point2f>(0,matches[i].queryIdx);
227
shape1.at<float>(i,0) = pt1.x;
228
shape1.at<float>(i,1) = pt1.y;
229
230
Point2f pt2=pts2.at<Point2f>(0,matches[i].trainIdx);
231
shape2.at<float>(i,0) = pt2.x;
232
shape2.at<float>(i,1) = pt2.y;
233
}
234
shape1.copyTo(shapeReference);
235
236
// Building the matrices for solving the L*(w|a)=(v|0) problem with L={[K|P];[P'|0]}
237
238
//Building K and P (Needed to build L)
239
Mat matK((int)matches.size(),(int)matches.size(),CV_32F);
240
Mat matP((int)matches.size(),3,CV_32F);
241
for (int i=0, end=(int)matches.size(); i<end; i++)
242
{
243
for (int j=0; j<end; j++)
244
{
245
if (i==j)
246
{
247
matK.at<float>(i,j)=float(regularizationParameter);
248
}
249
else
250
{
251
matK.at<float>(i,j) = distance(Point2f(shape1.at<float>(i,0),shape1.at<float>(i,1)),
252
Point2f(shape1.at<float>(j,0),shape1.at<float>(j,1)));
253
}
254
}
255
matP.at<float>(i,0) = 1;
256
matP.at<float>(i,1) = shape1.at<float>(i,0);
257
matP.at<float>(i,2) = shape1.at<float>(i,1);
258
}
259
260
//Building L
261
Mat matL=Mat::zeros((int)matches.size()+3,(int)matches.size()+3,CV_32F);
262
Mat matLroi(matL, Rect(0,0,(int)matches.size(),(int)matches.size())); //roi for K
263
matK.copyTo(matLroi);
264
matLroi = Mat(matL,Rect((int)matches.size(),0,3,(int)matches.size())); //roi for P
265
matP.copyTo(matLroi);
266
Mat matPt;
267
transpose(matP,matPt);
268
matLroi = Mat(matL,Rect(0,(int)matches.size(),(int)matches.size(),3)); //roi for P'
269
matPt.copyTo(matLroi);
270
271
//Building B (v|0)
272
Mat matB = Mat::zeros((int)matches.size()+3,2,CV_32F);
273
for (int i=0, end = (int)matches.size(); i<end; i++)
274
{
275
matB.at<float>(i,0) = shape2.at<float>(i,0); //x's
276
matB.at<float>(i,1) = shape2.at<float>(i,1); //y's
277
}
278
279
//Obtaining transformation params (w|a)
280
solve(matL, matB, tpsParameters, DECOMP_LU);
281
//tpsParameters = matL.inv()*matB;
282
283
//Setting transform Cost and Shape reference
284
Mat w(tpsParameters, Rect(0,0,2,tpsParameters.rows-3));
285
Mat Q=w.t()*matK*w;
286
transformCost=fabs(Q.at<float>(0,0)*Q.at<float>(1,1));//fabs(mean(Q.diag(0))[0]);//std::max(Q.at<float>(0,0),Q.at<float>(1,1));
287
tpsComputed=true;
288
}
289
290
Ptr <ThinPlateSplineShapeTransformer> createThinPlateSplineShapeTransformer(double regularizationParameter)
291
{
292
return Ptr<ThinPlateSplineShapeTransformer>( new ThinPlateSplineShapeTransformerImpl(regularizationParameter) );
293
}
294
295
} // cv
296
297