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) 2014, OpenCV Foundation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
21 //
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
25 //
26 // * The name of the copyright holders may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "../precomp.hpp"
43
44 #include "kyheader.hpp"
45 #include "CmTimer.hpp"
46 #include "CmFile.hpp"
47
48 namespace cv
49 {
50 namespace saliency
51 {
52
53 /**
54 * BING Objectness
55 */
56
57 const char* ObjectnessBING::_clrName[3] =
58 { "MAXBGR", "HSV", "I" };
59
ObjectnessBING()60 ObjectnessBING::ObjectnessBING()
61 {
62 _base = 2; // base for window size quantization
63 _W = 8; // feature window size (W, W)
64 _NSS = 2; //non-maximal suppress size NSS
65 _logBase = log( _base );
66 _minT = cvCeil( log( 10. ) / _logBase );
67 _maxT = cvCeil( log( 500. ) / _logBase );
68 _numT = _maxT - _minT + 1;
69 _Clr = MAXBGR;
70
71 setColorSpace( _Clr );
72
73 className = "BING";
74 }
75
~ObjectnessBING()76 ObjectnessBING::~ObjectnessBING()
77 {
78
79 }
80
setColorSpace(int clr)81 void ObjectnessBING::setColorSpace( int clr )
82 {
83 _Clr = clr;
84 _modelName = _trainingPath + "/" + std::string( format( "ObjNessB%gW%d%s", _base, _W, _clrName[_Clr] ).c_str() );
85 _bbResDir = _resultsDir + "/" + std::string( format( "BBoxesB%gW%d%s/", _base, _W, _clrName[_Clr] ).c_str() );
86 }
87
setTrainingPath(const String & trainingPath)88 void ObjectnessBING::setTrainingPath( const String& trainingPath )
89 {
90 _trainingPath = trainingPath;
91 }
92
setBBResDir(const String & resultsDir)93 void ObjectnessBING::setBBResDir(const String &resultsDir )
94 {
95 _resultsDir = resultsDir;
96 }
97
loadTrainedModel()98 int ObjectnessBING::loadTrainedModel() // Return -1, 0, or 1 if partial, none, or all loaded
99 {
100 CStr s1 = _modelName + ".wS1", s2 = _modelName + ".wS2", sI = _modelName + ".idx";
101 Mat filters1f, reW1f, idx1i, show3u;
102
103 if( !matRead( s1, filters1f ) || !matRead( sI, idx1i ) )
104 {
105 printf( "Can't load model: %s or %s\r\n", s1.c_str(), sI.c_str() );
106 return 0;
107 }
108
109
110 normalize( filters1f, show3u, 1, 255, NORM_MINMAX, CV_8U );
111 _tigF.update( filters1f );
112
113 _svmSzIdxs = idx1i;
114 CV_Assert( _svmSzIdxs.size() > 1 && filters1f.size() == Size(_W, _W) && filters1f.type() == CV_32F );
115 _svmFilter = filters1f;
116
117 if( !matRead( s2, _svmReW1f ) || _svmReW1f.size() != Size( 2, (int) _svmSzIdxs.size() ) )
118 {
119 _svmReW1f = Mat();
120 return -1;
121 }
122 return 1;
123 }
124
predictBBoxSI(Mat & img3u,ValStructVec<float,Vec4i> & valBoxes,std::vector<int> & sz,int NUM_WIN_PSZ,bool fast)125 void ObjectnessBING::predictBBoxSI( Mat &img3u, ValStructVec<float, Vec4i> &valBoxes, std::vector<int> &sz, int NUM_WIN_PSZ, bool fast )
126 {
127 const int numSz = (int) _svmSzIdxs.size();
128 const int imgW = img3u.cols, imgH = img3u.rows;
129 valBoxes.reserve( 10000 );
130 sz.clear();
131 sz.reserve( 10000 );
132 for ( int ir = numSz - 1; ir >= 0; ir-- )
133 {
134 int r = _svmSzIdxs[ir];
135 int height = cvRound( pow( _base, r / _numT + _minT ) ), width = cvRound( pow( _base, r % _numT + _minT ) );
136 if( height > imgH * _base || width > imgW * _base )
137 continue;
138
139 height = min( height, imgH ), width = min( width, imgW );
140 Mat im3u, matchCost1f, mag1u;
141 resize( img3u, im3u, Size( cvRound( _W * imgW * 1.0 / width ), cvRound( _W * imgH * 1.0 / height ) ), 0, 0, INTER_LINEAR_EXACT );
142 gradientMag( im3u, mag1u );
143
144 matchCost1f = _tigF.matchTemplate( mag1u );
145
146 ValStructVec<float, Point> matchCost;
147 nonMaxSup( matchCost1f, matchCost, _NSS, NUM_WIN_PSZ, fast );
148
149 // Find true locations and match values
150 double ratioX = width / _W, ratioY = height / _W;
151 int iMax = min( matchCost.size(), NUM_WIN_PSZ );
152 for ( int i = 0; i < iMax; i++ )
153 {
154 float mVal = matchCost( i );
155 Point pnt = matchCost[i];
156 Vec4i box( cvRound( pnt.x * ratioX ), cvRound( pnt.y * ratioY ) );
157 box[2] = cvRound( min( box[0] + width, imgW ) );
158 box[3] = cvRound( min( box[1] + height, imgH ) );
159 box[0]++;
160 box[1]++;
161 valBoxes.pushBack( mVal, box );
162 sz.push_back( ir );
163 }
164 }
165
166 }
167
predictBBoxSII(ValStructVec<float,Vec4i> & valBoxes,const std::vector<int> & sz)168 void ObjectnessBING::predictBBoxSII( ValStructVec<float, Vec4i> &valBoxes, const std::vector<int> &sz )
169 {
170 int numI = valBoxes.size();
171 for ( int i = 0; i < numI; i++ )
172 {
173 const float* svmIIw = _svmReW1f.ptr<float>( sz[i] );
174 valBoxes( i ) = valBoxes( i ) * svmIIw[0] + svmIIw[1];
175 }
176 //valBoxes.sort();
177 // Descending order. At the top there are the values with higher
178 // values, ie more likely to have objects in the their corresponding rectangles.
179 valBoxes.sort( true );
180 }
181
182 // Get potential bounding boxes, each of which is represented by a Vec4i for (minX, minY, maxX, maxY).
183 // The trained model should be prepared before calling this function: loadTrainedModel() or trainStageI() + trainStageII().
184 // Use numDet to control the final number of proposed bounding boxes, and number of per size (scale and aspect ratio)
getObjBndBoxes(Mat & img3u,ValStructVec<float,Vec4i> & valBoxes,int numDetPerSize)185 void ObjectnessBING::getObjBndBoxes( Mat &img3u, ValStructVec<float, Vec4i> &valBoxes, int numDetPerSize )
186 {
187 //CV_Assert_(filtersLoaded() , ("SVM filters should be initialized before getting object proposals\n"));
188 vecI sz;
189 predictBBoxSI( img3u, valBoxes, sz, numDetPerSize, false );
190 predictBBoxSII( valBoxes, sz );
191 return;
192 }
193
nonMaxSup(Mat & matchCost1f,ValStructVec<float,Point> & matchCost,int NSS,int maxPoint,bool fast)194 void ObjectnessBING::nonMaxSup( Mat &matchCost1f, ValStructVec<float, Point> &matchCost, int NSS, int maxPoint, bool fast )
195 {
196 const int _h = matchCost1f.rows, _w = matchCost1f.cols;
197 Mat isMax1u = Mat::ones( _h, _w, CV_8U ), costSmooth1f;
198 ValStructVec<float, Point> valPnt;
199 matchCost.reserve( _h * _w );
200 valPnt.reserve( _h * _w );
201 if( fast )
202 {
203 blur( matchCost1f, costSmooth1f, Size( 3, 3 ) );
204 for ( int r = 0; r < _h; r++ )
205 {
206 const float* d = matchCost1f.ptr<float>( r );
207 const float* ds = costSmooth1f.ptr<float>( r );
208 for ( int c = 0; c < _w; c++ )
209 if( d[c] >= ds[c] )
210 valPnt.pushBack( d[c], Point( c, r ) );
211 }
212 }
213 else
214 {
215 for ( int r = 0; r < _h; r++ )
216 {
217 const float* d = matchCost1f.ptr<float>( r );
218 for ( int c = 0; c < _w; c++ )
219 valPnt.pushBack( d[c], Point( c, r ) );
220 }
221 }
222
223 valPnt.sort();
224 for ( int i = 0; i < valPnt.size(); i++ )
225 {
226 Point &pnt = valPnt[i];
227 if( isMax1u.at<BYTE>( pnt ) )
228 {
229 matchCost.pushBack( valPnt( i ), pnt );
230 for ( int dy = -NSS; dy <= NSS; dy++ )
231 for ( int dx = -NSS; dx <= NSS; dx++ )
232 {
233 Point neighbor = pnt + Point( dx, dy );
234 if( !CHK_IND( neighbor ) )
235 continue;
236 isMax1u.at<BYTE>( neighbor ) = false;
237 }
238 }
239 if( matchCost.size() >= maxPoint )
240 return;
241 }
242 }
243
gradientMag(Mat & imgBGR3u,Mat & mag1u)244 void ObjectnessBING::gradientMag( Mat &imgBGR3u, Mat &mag1u )
245 {
246 switch ( _Clr )
247 {
248 case MAXBGR:
249 gradientRGB( imgBGR3u, mag1u );
250 break;
251 case G:
252 gradientGray( imgBGR3u, mag1u );
253 break;
254 case HSV:
255 gradientHSV( imgBGR3u, mag1u );
256 break;
257 default:
258 printf( "Error: not recognized color space\n" );
259 }
260 }
261
gradientRGB(Mat & bgr3u,Mat & mag1u)262 void ObjectnessBING::gradientRGB( Mat &bgr3u, Mat &mag1u )
263 {
264 const int H = bgr3u.rows, W = bgr3u.cols;
265 Mat Ix( H, W, CV_32S ), Iy( H, W, CV_32S );
266
267 // Left/right most column Ix
268 for ( int y = 0; y < H; y++ )
269 {
270 Ix.at<int>( y, 0 ) = bgrMaxDist( bgr3u.at<Vec3b>( y, 1 ), bgr3u.at<Vec3b>( y, 0 ) ) * 2;
271 Ix.at<int>( y, W - 1 ) = bgrMaxDist( bgr3u.at<Vec3b>( y, W - 1 ), bgr3u.at<Vec3b>( y, W - 2 ) ) * 2;
272 }
273
274 // Top/bottom most column Iy
275 for ( int x = 0; x < W; x++ )
276 {
277 Iy.at<int>( 0, x ) = bgrMaxDist( bgr3u.at<Vec3b>( 1, x ), bgr3u.at<Vec3b>( 0, x ) ) * 2;
278 Iy.at<int>( H - 1, x ) = bgrMaxDist( bgr3u.at<Vec3b>( H - 1, x ), bgr3u.at<Vec3b>( H - 2, x ) ) * 2;
279 }
280
281 // Find the gradient for inner regions
282 for ( int y = 0; y < H; y++ )
283 {
284 const Vec3b *dataP = bgr3u.ptr<Vec3b>( y );
285 for ( int x = 2; x < W; x++ )
286 Ix.at<int>( y, x - 1 ) = bgrMaxDist( dataP[x - 2], dataP[x] ); // bgr3u.at<Vec3b>(y, x+1), bgr3u.at<Vec3b>(y, x-1));
287 }
288 for ( int y = 1; y < H - 1; y++ )
289 {
290 const Vec3b *tP = bgr3u.ptr<Vec3b>( y - 1 );
291 const Vec3b *bP = bgr3u.ptr<Vec3b>( y + 1 );
292 for ( int x = 0; x < W; x++ )
293 Iy.at<int>( y, x ) = bgrMaxDist( tP[x], bP[x] );
294 }
295 gradientXY( Ix, Iy, mag1u );
296 }
297
gradientGray(Mat & bgr3u,Mat & mag1u)298 void ObjectnessBING::gradientGray( Mat &bgr3u, Mat &mag1u )
299 {
300 Mat g1u;
301 cvtColor( bgr3u, g1u, COLOR_BGR2GRAY );
302 const int H = g1u.rows, W = g1u.cols;
303 Mat Ix( H, W, CV_32S ), Iy( H, W, CV_32S );
304
305 // Left/right most column Ix
306 for ( int y = 0; y < H; y++ )
307 {
308 Ix.at<int>( y, 0 ) = abs( g1u.at<BYTE>( y, 1 ) - g1u.at<BYTE>( y, 0 ) ) * 2;
309 Ix.at<int>( y, W - 1 ) = abs( g1u.at<BYTE>( y, W - 1 ) - g1u.at<BYTE>( y, W - 2 ) ) * 2;
310 }
311
312 // Top/bottom most column Iy
313 for ( int x = 0; x < W; x++ )
314 {
315 Iy.at<int>( 0, x ) = abs( g1u.at<BYTE>( 1, x ) - g1u.at<BYTE>( 0, x ) ) * 2;
316 Iy.at<int>( H - 1, x ) = abs( g1u.at<BYTE>( H - 1, x ) - g1u.at<BYTE>( H - 2, x ) ) * 2;
317 }
318
319 // Find the gradient for inner regions
320 for ( int y = 0; y < H; y++ )
321 for ( int x = 1; x < W - 1; x++ )
322 Ix.at<int>( y, x ) = abs( g1u.at<BYTE>( y, x + 1 ) - g1u.at<BYTE>( y, x - 1 ) );
323 for ( int y = 1; y < H - 1; y++ )
324 for ( int x = 0; x < W; x++ )
325 Iy.at<int>( y, x ) = abs( g1u.at<BYTE>( y + 1, x ) - g1u.at<BYTE>( y - 1, x ) );
326
327 gradientXY( Ix, Iy, mag1u );
328 }
329
gradientHSV(Mat & bgr3u,Mat & mag1u)330 void ObjectnessBING::gradientHSV( Mat &bgr3u, Mat &mag1u )
331 {
332 Mat hsv3u;
333 cvtColor( bgr3u, hsv3u, COLOR_BGR2HSV );
334 const int H = hsv3u.rows, W = hsv3u.cols;
335 Mat Ix( H, W, CV_32S ), Iy( H, W, CV_32S );
336
337 // Left/right most column Ix
338 for ( int y = 0; y < H; y++ )
339 {
340 Ix.at<int>( y, 0 ) = vecDist3b( hsv3u.at<Vec3b>( y, 1 ), hsv3u.at<Vec3b>( y, 0 ) );
341 Ix.at<int>( y, W - 1 ) = vecDist3b( hsv3u.at<Vec3b>( y, W - 1 ), hsv3u.at<Vec3b>( y, W - 2 ) );
342 }
343
344 // Top/bottom most column Iy
345 for ( int x = 0; x < W; x++ )
346 {
347 Iy.at<int>( 0, x ) = vecDist3b( hsv3u.at<Vec3b>( 1, x ), hsv3u.at<Vec3b>( 0, x ) );
348 Iy.at<int>( H - 1, x ) = vecDist3b( hsv3u.at<Vec3b>( H - 1, x ), hsv3u.at<Vec3b>( H - 2, x ) );
349 }
350
351 // Find the gradient for inner regions
352 for ( int y = 0; y < H; y++ )
353 for ( int x = 1; x < W - 1; x++ )
354 Ix.at<int>( y, x ) = vecDist3b( hsv3u.at<Vec3b>( y, x + 1 ), hsv3u.at<Vec3b>( y, x - 1 ) ) / 2;
355 for ( int y = 1; y < H - 1; y++ )
356 for ( int x = 0; x < W; x++ )
357 Iy.at<int>( y, x ) = vecDist3b( hsv3u.at<Vec3b>( y + 1, x ), hsv3u.at<Vec3b>( y - 1, x ) ) / 2;
358
359 gradientXY( Ix, Iy, mag1u );
360 }
361
gradientXY(Mat & x1i,Mat & y1i,Mat & mag1u)362 void ObjectnessBING::gradientXY( Mat &x1i, Mat &y1i, Mat &mag1u )
363 {
364 const int H = x1i.rows, W = x1i.cols;
365 mag1u.create( H, W, CV_8U );
366 for ( int r = 0; r < H; r++ )
367 {
368 const int *x = x1i.ptr<int>( r ), *y = y1i.ptr<int>( r );
369 BYTE* m = mag1u.ptr<BYTE>( r );
370 for ( int c = 0; c < W; c++ )
371 m[c] = (BYTE) min( x[c] + y[c], 255 ); //((int)sqrt(sqr(x[c]) + sqr(y[c])), 255);
372 }
373 }
374
getObjBndBoxesForSingleImage(Mat img,ValStructVec<float,Vec4i> & finalBoxes,int numDetPerSize)375 void ObjectnessBING::getObjBndBoxesForSingleImage( Mat img, ValStructVec<float, Vec4i> &finalBoxes, int numDetPerSize )
376 {
377 ValStructVec<float, Vec4i> boxes;
378 finalBoxes.reserve( 10000 );
379
380 int scales[3] =
381 { 1, 3, 5 };
382 for ( int clr = MAXBGR; clr <= G; clr++ )
383 {
384 setColorSpace( clr );
385 if (!loadTrainedModel())
386 continue;
387
388 CmTimer tm( "Predict" );
389 tm.Start();
390
391 getObjBndBoxes( img, boxes, numDetPerSize );
392 finalBoxes.append( boxes, scales[clr] );
393
394 tm.Stop();
395 printf( "Average time for predicting an image (%s) is %gs\n", _clrName[_Clr], tm.TimeInSeconds() );
396 }
397
398 //Write on file the total number and the list of rectangles returned by objectess, one for each row.
399
400 CmFile::MkDir( _bbResDir );
401 CStr fName = _bbResDir + "bb";
402 std::vector<Vec4i> sortedBB = finalBoxes.getSortedStructVal();
403 std::ofstream ofs;
404 ofs.open( ( fName + ".txt" ).c_str(), std::ofstream::out );
405 std::stringstream dim;
406 dim << sortedBB.size();
407 ofs << dim.str() << "\n";
408 for ( size_t k = 0; k < sortedBB.size(); k++ )
409 {
410 std::stringstream str;
411 str << sortedBB[k][0] << " " << sortedBB[k][1] << " " << sortedBB[k][2] << " " << sortedBB[k][3] << "\n";
412 ofs << str.str();
413 }
414 ofs.close();
415 }
416
417 struct MatchPathSeparator
418 {
operator ()cv::saliency::MatchPathSeparator419 bool operator()( char ch ) const
420 {
421 return ch == '/';
422 }
423 };
424
basename(std::string const & pathname)425 std::string inline basename( std::string const& pathname )
426 {
427 return std::string( std::find_if( pathname.rbegin(), pathname.rend(), MatchPathSeparator() ).base(), pathname.end() );
428 }
429
removeExtension(std::string const & filename)430 std::string inline removeExtension( std::string const& filename )
431 {
432 std::string::const_reverse_iterator pivot = std::find( filename.rbegin(), filename.rend(), '.' );
433 return pivot == filename.rend() ? filename : std::string( filename.begin(), pivot.base() - 1 );
434 }
435
436 // Read matrix from binary file
matRead(const std::string & filename,Mat & _M)437 bool ObjectnessBING::matRead( const std::string& filename, Mat& _M )
438 {
439 String filenamePlusExt( filename.c_str() );
440 filenamePlusExt += ".yml.gz";
441 FileStorage fs2( filenamePlusExt, FileStorage::READ );
442 if (! fs2.isOpened()) // wrong trainingPath
443 return false;
444
445 Mat M;
446 fs2[String( removeExtension( basename( filename ) ).c_str() )] >> M;
447
448 M.copyTo( _M );
449 return true;
450 }
getobjectnessValues()451 std::vector<float> ObjectnessBING::getobjectnessValues()
452 {
453 return objectnessValues;
454 }
455
read()456 void ObjectnessBING::read()
457 {
458
459 }
460
write() const461 void ObjectnessBING::write() const
462 {
463
464 }
465
computeSaliencyImpl(InputArray image,OutputArray objectnessBoundingBox)466 bool ObjectnessBING::computeSaliencyImpl( InputArray image, OutputArray objectnessBoundingBox )
467 {
468 ValStructVec<float, Vec4i> finalBoxes;
469 getObjBndBoxesForSingleImage( image.getMat(), finalBoxes, 250 );
470
471 // List of rectangles returned by objectess function in descending order.
472 // At the top there are the rectangles with higher values, ie more
473 // likely to have objects in them.
474 std::vector<Vec4i> sortedBB = finalBoxes.getSortedStructVal();
475 Mat( sortedBB ).copyTo( objectnessBoundingBox );
476
477 // List of the rectangles' objectness value
478 unsigned long int valIdxesSize = (unsigned long int) finalBoxes.getvalIdxes().size();
479 objectnessValues.resize( valIdxesSize );
480 for ( uint i = 0; i < valIdxesSize; i++ )
481 objectnessValues[finalBoxes.getvalIdxes()[i].second] = finalBoxes.getvalIdxes()[i].first;
482
483 return true;
484 }
485
486 template<typename VT, typename ST>
append(const ValStructVec<VT,ST> & newVals,int startV)487 void ObjectnessBING::ValStructVec<VT, ST>::append( const ValStructVec<VT, ST> &newVals, int startV )
488 {
489 int newValsSize = newVals.size();
490 for ( int i = 0; i < newValsSize; i++ )
491 pushBack( (float) ( ( i + 300 ) * startV ), newVals[i] );
492 }
493
494 template<typename VT, typename ST>
sort(bool descendOrder)495 void ObjectnessBING::ValStructVec<VT, ST>::sort( bool descendOrder /* = true */)
496 {
497 if( descendOrder )
498 std::sort( valIdxes.begin(), valIdxes.end(), std::greater<std::pair<VT, int> >() );
499 else
500 std::sort( valIdxes.begin(), valIdxes.end(), std::less<std::pair<VT, int> >() );
501 }
502
503 template<typename VT, typename ST>
getSortedStructVal()504 const std::vector<ST>& ObjectnessBING::ValStructVec<VT, ST>::getSortedStructVal()
505 {
506 sortedStructVals.resize( sz );
507 for ( int i = 0; i < sz; i++ )
508 sortedStructVals[i] = structVals[valIdxes[i].second];
509 return sortedStructVals;
510 }
511
512 template<typename VT, typename ST>
getvalIdxes()513 std::vector<std::pair<VT, int> > ObjectnessBING::ValStructVec<VT, ST>::getvalIdxes()
514 {
515 return valIdxes;
516 }
517
518 template<typename VT, typename ST>
ValStructVec()519 ObjectnessBING::ValStructVec<VT, ST>::ValStructVec()
520 {
521 clear();
522 }
523
524 template<typename VT, typename ST>
size() const525 int ObjectnessBING::ValStructVec<VT, ST>::size() const
526 {
527 return sz;
528 }
529
530 template<typename VT, typename ST>
clear()531 void ObjectnessBING::ValStructVec<VT, ST>::clear()
532 {
533 sz = 0;
534 structVals.clear();
535 valIdxes.clear();
536 }
537
538 template<typename VT, typename ST>
reserve(int resSz)539 void ObjectnessBING::ValStructVec<VT, ST>::reserve( int resSz )
540 {
541 clear();
542 structVals.reserve( resSz );
543 valIdxes.reserve( resSz );
544 }
545
546 template<typename VT, typename ST>
pushBack(const VT & val,const ST & structVal)547 void ObjectnessBING::ValStructVec<VT, ST>::pushBack( const VT& val, const ST& structVal )
548 {
549 valIdxes.push_back( std::make_pair( val, sz ) );
550 structVals.push_back( structVal );
551 sz++;
552 }
553
554 template<typename VT, typename ST>
operator ()(int i) const555 const VT& ObjectnessBING::ValStructVec<VT, ST>::operator ()( int i ) const
556 {
557 return valIdxes[i].first;
558 } // Should be called after sort
559
560 template<typename VT, typename ST>
operator [](int i) const561 const ST& ObjectnessBING::ValStructVec<VT, ST>::operator []( int i ) const
562 {
563 return structVals[valIdxes[i].second];
564 } // Should be called after sort
565
566 template<typename VT, typename ST>
567 VT& ObjectnessBING::ValStructVec<VT, ST>::operator ()( int i )
568 {
569 return valIdxes[i].first;
570 } // Should be called after sort
571
572 template<typename VT, typename ST>
operator [](int i)573 ST& ObjectnessBING::ValStructVec<VT, ST>::operator []( int i )
574 {
575 return structVals[valIdxes[i].second];
576 }
577
578 } /* namespace saliency */
579 }/* namespace cv */
580