@@ -85,7 +85,92 @@ static void findCorrespondenciesOLS(const cv::Mat_<float>& scores, cv::Mat_<int>
85
85
}
86
86
}
87
87
88
- struct OLSTrackerImpl : public OLSTracker
88
+ static float computeEdgeWeight (const cv::Vec2s& curCandiPoint, const cv::Vec2s& preCandiPoint)
89
+ {
90
+ float spatial_dist = (float )cv::norm (curCandiPoint - preCandiPoint, cv::NORM_L2SQR);
91
+ return std::exp (-spatial_dist/1000 .0f );
92
+ }
93
+
94
+ static void findCorrespondenciesGOS (Mat& bundleGrad, Mat_<float >& fgScores, Mat_<float >& bgScores,
95
+ const Mat_<Vec2s>& imgLocations, Mat_<int >& cols)
96
+ {
97
+ // combine scores
98
+ Mat_<float > scores;
99
+ exp ((fgScores + bgScores)/10 .0f , scores);
100
+
101
+ Mat_<int > fromLocations (scores.size ());
102
+ fromLocations = 0 ;
103
+
104
+ // source node
105
+ bool hasCandidate = false ;
106
+ for (int j=0 ; j<bundleGrad.cols ; j++)
107
+ {
108
+ if (bundleGrad.at <uchar>(0 , j))
109
+ {
110
+ hasCandidate = true ;
111
+ fromLocations (0 , j) = j;
112
+ }
113
+ }
114
+ // fall back to using center as candidate
115
+ if (!hasCandidate)
116
+ {
117
+ fromLocations (0 , bundleGrad.cols /2 ) = bundleGrad.cols /2 ;
118
+ }
119
+
120
+ int index_max_location = 0 ; // index in preceding line for backtracking
121
+
122
+ // the other layers
123
+ for (int i=1 ; i<bundleGrad.rows ; i++)
124
+ {
125
+ hasCandidate = false ;
126
+ for (int j=0 ; j<bundleGrad.cols ; j++)
127
+ {
128
+ if (bundleGrad.at <uchar>(i, j))
129
+ hasCandidate = true ;
130
+ }
131
+ if (!hasCandidate)
132
+ {
133
+ bundleGrad.at <uchar>(i, bundleGrad.cols /2 ) = 255 ;
134
+ }
135
+
136
+ for (int j=0 ; j<bundleGrad.cols ; j++)
137
+ {
138
+ // search for max combined score
139
+ float max_energy = -INFINITY;
140
+ int location = bundleGrad.cols /2 ;
141
+
142
+ if (bundleGrad.at <uchar>(i, j))
143
+ {
144
+ for (int k=0 ; k<bundleGrad.cols ; k++)
145
+ {
146
+ if (bundleGrad.at <uchar>(i - 1 , k))
147
+ {
148
+ float edge_weight = computeEdgeWeight (imgLocations (i, j), imgLocations (i - 1 , k));
149
+ float energy = scores (i, j) + scores (i-1 , k) + edge_weight;
150
+ if (max_energy < energy)
151
+ {
152
+ max_energy = energy;
153
+ location = k;
154
+ }
155
+ }
156
+ }
157
+
158
+ scores (i, j) = max_energy; // update the score
159
+ fromLocations (i, j) = location;
160
+ index_max_location = j;
161
+ }
162
+ }
163
+ }
164
+
165
+ // backtrack along best path
166
+ for (int i = bundleGrad.rows - 1 ; i >= 0 ; i--)
167
+ {
168
+ cols (i) = index_max_location;
169
+ index_max_location = fromLocations (i, index_max_location);
170
+ }
171
+ }
172
+
173
+ struct HistTrackerImpl : public OLSTracker
89
174
{
90
175
Mat vtx;
91
176
Mat tris;
@@ -95,15 +180,18 @@ struct OLSTrackerImpl : public OLSTracker
95
180
double tau;
96
181
uchar sobelThresh;
97
182
98
- OLSTrackerImpl (InputArray _pts3d, InputArray _tris, int histBins, uchar _sobelThesh)
183
+ bool useGOS;
184
+
185
+ HistTrackerImpl (InputArray _pts3d, InputArray _tris, int histBins, uchar _sobelThesh, bool _useGOS)
99
186
{
100
187
CV_Assert (_tris.getMat ().checkVector (3 , CV_32S) > 0 );
101
188
CV_Assert (_pts3d.getMat ().checkVector (3 , CV_32F) > 0 );
102
189
vtx = _pts3d.getMat ();
103
190
tris = _tris.getMat ();
104
191
105
- tau = 1.0 ; // currently does not work as intended. effectively disable
192
+ tau = 0.7 ; // this is 1 - tau compared to OLS paper
106
193
sobelThresh = _sobelThesh;
194
+ useGOS = _useGOS;
107
195
108
196
bgHist.create (histBins, histBins);
109
197
}
@@ -129,7 +217,7 @@ struct OLSTrackerImpl : public OLSTracker
129
217
130
218
double s = bhattacharyyaCoeff (fgHist, hist);
131
219
// handle object clutter as in eq. (5)
132
- if (( 1.0 - s) > tau)
220
+ if (s > tau)
133
221
s = 1.0 - bhattacharyyaCoeff (bgHist, hist);
134
222
scores (i, j) = float (s);
135
223
start = j;
@@ -138,6 +226,36 @@ struct OLSTrackerImpl : public OLSTracker
138
226
}
139
227
}
140
228
229
+ void computeBackgroundScores (const Mat& bundleHSV, const Mat& bundleGrad, Mat_<float >& scores)
230
+ {
231
+ scores.resize (bundleHSV.rows );
232
+ scores = 0 ;
233
+
234
+ Mat_<float > hist (fgHist.size ());
235
+
236
+ for (int i = 0 ; i < bundleHSV.rows ; i++)
237
+ {
238
+ int end = bundleHSV.cols - 1 ;
239
+ for (int j = bundleHSV.cols - 1 ; j >= 0 ; j--)
240
+ {
241
+ if (bundleGrad.at <uchar>(i, j))
242
+ {
243
+ // compute the histogram between last candidate point to current candidate point
244
+ hist = 0 ;
245
+ calcHueSatHist (bundleHSV ({i, i + 1 }, {j, end}), hist);
246
+ hist /= std::max (sum (hist), 1 .0f );
247
+
248
+ double s = 1 - bhattacharyyaCoeff (fgHist, hist);
249
+ if (s <= tau)
250
+ s = bhattacharyyaCoeff (bgHist, hist);
251
+
252
+ scores (i, j) = float (s);
253
+ end = j;
254
+ }
255
+ }
256
+ }
257
+ }
258
+
141
259
void updateFgBgHist (const Mat_<Vec3b>& hsv, const Mat_<int >& cols)
142
260
{
143
261
fgHist = 0 ;
@@ -189,7 +307,17 @@ struct OLSTrackerImpl : public OLSTracker
189
307
190
308
Mat_<float > scores (lineBundle.size ());
191
309
computeAppearanceScores (bundleHSV, bundleGrad, scores);
192
- findCorrespondenciesOLS (scores, cols);
310
+
311
+ if (useGOS)
312
+ {
313
+ Mat_<float > bgScores (scores.size ());
314
+ computeBackgroundScores (bundleHSV, bundleGrad, bgScores);
315
+ findCorrespondenciesGOS (bundleGrad, scores, bgScores, imgLoc, cols);
316
+ }
317
+ else
318
+ {
319
+ findCorrespondenciesOLS (scores, cols);
320
+ }
193
321
194
322
convertCorrespondencies (cols, imgLoc, pts2d, pts3d, cols > -1 );
195
323
@@ -224,7 +352,12 @@ struct OLSTrackerImpl : public OLSTracker
224
352
225
353
Ptr<OLSTracker> OLSTracker::create (InputArray pts3d, InputArray tris, int histBins, uchar sobelThesh)
226
354
{
227
- return makePtr<OLSTrackerImpl>(pts3d, tris, histBins, sobelThesh);
355
+ return makePtr<HistTrackerImpl>(pts3d, tris, histBins, sobelThesh, false );
356
+ }
357
+
358
+ Ptr<OLSTracker> GOSTracker::create (InputArray pts3d, InputArray tris, int histBins, uchar sobelThesh)
359
+ {
360
+ return makePtr<HistTrackerImpl>(pts3d, tris, histBins, sobelThesh, true );
228
361
}
229
362
230
363
} // namespace rapid
0 commit comments