@@ -85,7 +85,94 @@ static void findCorrespondenciesOLS(const cv::Mat_<float>& scores, cv::Mat_<int>
8585 }
8686}
8787
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+ cols.resize (scores.rows );
166+
167+ // backtrack along best path
168+ for (int i = bundleGrad.rows - 1 ; i >= 0 ; i--)
169+ {
170+ cols (i) = index_max_location;
171+ index_max_location = fromLocations (i, index_max_location);
172+ }
173+ }
174+
175+ struct HistTrackerImpl : public OLSTracker
89176{
90177 Mat vtx;
91178 Mat tris;
@@ -95,15 +182,18 @@ struct OLSTrackerImpl : public OLSTracker
95182 double tau;
96183 uchar sobelThresh;
97184
98- OLSTrackerImpl (InputArray _pts3d, InputArray _tris, int histBins, uchar _sobelThesh)
185+ bool useGOS;
186+
187+ HistTrackerImpl (InputArray _pts3d, InputArray _tris, int histBins, uchar _sobelThesh, bool _useGOS)
99188 {
100189 CV_Assert (_tris.getMat ().checkVector (3 , CV_32S) > 0 );
101190 CV_Assert (_pts3d.getMat ().checkVector (3 , CV_32F) > 0 );
102191 vtx = _pts3d.getMat ();
103192 tris = _tris.getMat ();
104193
105- tau = 1.0 ; // currently does not work as intended. effectively disable
194+ tau = 0.7 ; // this is 1 - tau compared to OLS paper
106195 sobelThresh = _sobelThesh;
196+ useGOS = _useGOS;
107197
108198 bgHist.create (histBins, histBins);
109199 }
@@ -129,7 +219,7 @@ struct OLSTrackerImpl : public OLSTracker
129219
130220 double s = bhattacharyyaCoeff (fgHist, hist);
131221 // handle object clutter as in eq. (5)
132- if (( 1.0 - s) > tau)
222+ if (s > tau)
133223 s = 1.0 - bhattacharyyaCoeff (bgHist, hist);
134224 scores (i, j) = float (s);
135225 start = j;
@@ -138,6 +228,36 @@ struct OLSTrackerImpl : public OLSTracker
138228 }
139229 }
140230
231+ void computeBackgroundScores (const Mat& bundleHSV, const Mat& bundleGrad, Mat_<float >& scores)
232+ {
233+ scores.resize (bundleHSV.rows );
234+ scores = 0 ;
235+
236+ Mat_<float > hist (fgHist.size ());
237+
238+ for (int i = 0 ; i < bundleHSV.rows ; i++)
239+ {
240+ int end = bundleHSV.cols - 1 ;
241+ for (int j = bundleHSV.cols - 1 ; j >= 0 ; j--)
242+ {
243+ if (bundleGrad.at <uchar>(i, j))
244+ {
245+ // compute the histogram between last candidate point to current candidate point
246+ hist = 0 ;
247+ calcHueSatHist (bundleHSV ({i, i + 1 }, {j, end}), hist);
248+ hist /= std::max (sum (hist), 1 .0f );
249+
250+ double s = 1 - bhattacharyyaCoeff (fgHist, hist);
251+ if (s <= tau)
252+ s = bhattacharyyaCoeff (bgHist, hist);
253+
254+ scores (i, j) = float (s);
255+ end = j;
256+ }
257+ }
258+ }
259+ }
260+
141261 void updateFgBgHist (const Mat_<Vec3b>& hsv, const Mat_<int >& cols)
142262 {
143263 fgHist = 0 ;
@@ -189,7 +309,17 @@ struct OLSTrackerImpl : public OLSTracker
189309
190310 Mat_<float > scores (lineBundle.size ());
191311 computeAppearanceScores (bundleHSV, bundleGrad, scores);
192- findCorrespondenciesOLS (scores, cols);
312+
313+ if (useGOS)
314+ {
315+ Mat_<float > bgScores (scores.size ());
316+ computeBackgroundScores (bundleHSV, bundleGrad, bgScores);
317+ findCorrespondenciesGOS (bundleGrad, scores, bgScores, imgLoc, cols);
318+ }
319+ else
320+ {
321+ findCorrespondenciesOLS (scores, cols);
322+ }
193323
194324 convertCorrespondencies (cols, imgLoc, pts2d, pts3d, cols > -1 );
195325
@@ -224,7 +354,12 @@ struct OLSTrackerImpl : public OLSTracker
224354
225355Ptr<OLSTracker> OLSTracker::create (InputArray pts3d, InputArray tris, int histBins, uchar sobelThesh)
226356{
227- return makePtr<OLSTrackerImpl>(pts3d, tris, histBins, sobelThesh);
357+ return makePtr<HistTrackerImpl>(pts3d, tris, histBins, sobelThesh, false );
358+ }
359+
360+ Ptr<OLSTracker> GOSTracker::create (InputArray pts3d, InputArray tris, int histBins, uchar sobelThesh)
361+ {
362+ return makePtr<HistTrackerImpl>(pts3d, tris, histBins, sobelThesh, true );
228363}
229364
230365} // namespace rapid
0 commit comments