Skip to content

Commit a3028b1

Browse files
author
Carsten Griwodz
committed
[feature] support float input images
1 parent 29a2da3 commit a3028b1

File tree

9 files changed

+395
-69
lines changed

9 files changed

+395
-69
lines changed

src/application/main.cpp

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static bool print_time_info = false;
4343
static bool write_as_uchar = false;
4444
static bool dont_write = false;
4545
static bool pgmread_loading = false;
46+
static bool float_mode = false;
4647

4748
static void parseargs(int argc, char** argv, popsift::Config& config, string& inputFile) {
4849
using namespace boost::program_options;
@@ -118,6 +119,7 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
118119
"Scaling to sensible ranges is not automatic, should be combined with --norm-multi=9 or similar")
119120
("dont-write", bool_switch(&dont_write)->default_value(false), "Suppress descriptor output")
120121
("pgmread-loading", bool_switch(&pgmread_loading)->default_value(false), "Use the old image loader instead of LibDevIL")
122+
("float-mode", bool_switch(&float_mode)->default_value(false), "Upload image to GPU as float instead of byte")
121123
;
122124

123125
//("test-direct-scaling")
@@ -167,12 +169,18 @@ SiftJob* process_image( const string& inputFile, PopSift& PopSift )
167169
{
168170
int w;
169171
int h;
170-
unsigned char* image_data;
171172
SiftJob* job;
173+
unsigned char* image_data;
172174

173175
#ifdef USE_DEVIL
174176
if( not pgmread_loading )
175177
{
178+
if( float_mode )
179+
{
180+
cerr << "Cannot combine float-mode test with DevIL image reader" << endl;
181+
exit( -1 );
182+
}
183+
176184
nvtxRangePushA( "load and convert image - devil" );
177185

178186
ilImage img;
@@ -187,11 +195,11 @@ SiftJob* process_image( const string& inputFile, PopSift& PopSift )
187195
w = img.Width();
188196
h = img.Height();
189197
cout << "Loading " << w << " x " << h << " image " << inputFile << endl;
198+
190199
image_data = img.GetData();
191200

192201
nvtxRangePop( ); // "load and convert image - devil"
193202

194-
// PopSift.init( w, h );
195203
job = PopSift.enqueue( w, h, image_data );
196204

197205
img.Clear();
@@ -208,10 +216,25 @@ SiftJob* process_image( const string& inputFile, PopSift& PopSift )
208216

209217
nvtxRangePop( ); // "load and convert image - pgmread"
210218

211-
// PopSift.init( w, h );
212-
job = PopSift.enqueue( w, h, image_data );
219+
if( not float_mode )
220+
{
221+
// PopSift.init( w, h );
222+
job = PopSift.enqueue( w, h, image_data );
213223

214-
delete [] image_data;
224+
delete [] image_data;
225+
}
226+
else
227+
{
228+
float* f_image_data = new float [w * h];
229+
for( int i=0; i<w*h; i++ )
230+
{
231+
f_image_data[i] = float( image_data[i] ) / 256.0f;
232+
}
233+
job = PopSift.enqueue( w, h, f_image_data );
234+
235+
delete [] image_data;
236+
delete [] f_image_data;
237+
}
215238
}
216239

217240
return job;
@@ -275,7 +298,9 @@ int main(int argc, char **argv)
275298
deviceInfo.set( 0, print_dev_info );
276299
if( print_dev_info ) deviceInfo.print( );
277300

278-
PopSift PopSift( config );
301+
PopSift PopSift( config,
302+
popsift::Config::ExtractingMode,
303+
float_mode ? PopSift::FloatImages : PopSift::ByteImages );
279304

280305
std::queue<SiftJob*> jobs;
281306
for( auto it = inputFiles.begin(); it!=inputFiles.end(); it++ ) {

src/popsift/popsift.cu

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,19 @@
1919

2020
using namespace std;
2121

22-
PopSift::PopSift( const popsift::Config& config, popsift::Config::ProcessingMode mode )
22+
PopSift::PopSift( const popsift::Config& config, popsift::Config::ProcessingMode mode, ImageMode imode )
23+
: _image_mode( imode )
2324
{
24-
_pipe._unused.push( new popsift::Image );
25-
_pipe._unused.push( new popsift::Image );
25+
if( imode == ByteImages )
26+
{
27+
_pipe._unused.push( new popsift::Image);
28+
_pipe._unused.push( new popsift::Image);
29+
}
30+
else
31+
{
32+
_pipe._unused.push( new popsift::ImageFloat );
33+
_pipe._unused.push( new popsift::ImageFloat );
34+
}
2635
_pipe._pyramid = 0;
2736

2837
configure( config, true );
@@ -34,10 +43,19 @@ PopSift::PopSift( const popsift::Config& config, popsift::Config::ProcessingMode
3443
_pipe._thread_stage2 = new boost::thread( &PopSift::matchPrepareLoop, this );
3544
}
3645

37-
PopSift::PopSift( )
46+
PopSift::PopSift( ImageMode imode )
47+
: _image_mode( imode )
3848
{
39-
_pipe._unused.push( new popsift::Image );
40-
_pipe._unused.push( new popsift::Image );
49+
if( imode == ByteImages )
50+
{
51+
_pipe._unused.push( new popsift::Image);
52+
_pipe._unused.push( new popsift::Image);
53+
}
54+
else
55+
{
56+
_pipe._unused.push( new popsift::ImageFloat );
57+
_pipe._unused.push( new popsift::ImageFloat );
58+
}
4159
_pipe._pyramid = 0;
4260

4361
_pipe._thread_stage1 = new boost::thread( &PopSift::uploadImages, this );
@@ -117,7 +135,7 @@ void PopSift::uninit( )
117135
delete _pipe._thread_stage1;
118136

119137
while( !_pipe._unused.empty() ) {
120-
popsift::Image* img = _pipe._unused.pull();
138+
popsift::ImageBase* img = _pipe._unused.pull();
121139
delete img;
122140
}
123141

@@ -129,6 +147,29 @@ SiftJob* PopSift::enqueue( int w,
129147
int h,
130148
const unsigned char* imageData )
131149
{
150+
if( _image_mode != ByteImages )
151+
{
152+
cerr << __FILE__ << ":" << __LINE__ << " Image mode error" << endl
153+
<< "E Cannot load byte images into a PopSift pipeline configured for float images" << endl;
154+
exit( -1 );
155+
}
156+
157+
SiftJob* job = new SiftJob( w, h, imageData );
158+
_pipe._queue_stage1.push( job );
159+
return job;
160+
}
161+
162+
SiftJob* PopSift::enqueue( int w,
163+
int h,
164+
const float* imageData )
165+
{
166+
if( _image_mode != FloatImages )
167+
{
168+
cerr << __FILE__ << ":" << __LINE__ << " Image mode error" << endl
169+
<< "E Cannot load float images into a PopSift pipeline configured for byte images" << endl;
170+
exit( -1 );
171+
}
172+
132173
SiftJob* job = new SiftJob( w, h, imageData );
133174
_pipe._queue_stage1.push( job );
134175
return job;
@@ -138,7 +179,7 @@ void PopSift::uploadImages( )
138179
{
139180
SiftJob* job;
140181
while( ( job = _pipe._queue_stage1.pull() ) != 0 ) {
141-
popsift::Image* img = _pipe._unused.pull();
182+
popsift::ImageBase* img = _pipe._unused.pull();
142183
job->setImg( img );
143184
_pipe._queue_stage2.push( job );
144185
}
@@ -151,7 +192,7 @@ void PopSift::extractDownloadLoop( )
151192

152193
SiftJob* job;
153194
while( ( job = p._queue_stage2.pull() ) != 0 ) {
154-
popsift::Image* img = job->getImg();
195+
popsift::ImageBase* img = job->getImg();
155196

156197
private_init( img->getWidth(), img->getHeight() );
157198

@@ -186,7 +227,7 @@ void PopSift::matchPrepareLoop( )
186227

187228
SiftJob* job;
188229
while( ( job = p._queue_stage2.pull() ) != 0 ) {
189-
popsift::Image* img = job->getImg();
230+
popsift::ImageBase* img = job->getImg();
190231

191232
private_init( img->getWidth(), img->getHeight() );
192233

@@ -220,19 +261,36 @@ SiftJob::SiftJob( int w, int h, const unsigned char* imageData )
220261
}
221262
}
222263

264+
SiftJob::SiftJob( int w, int h, const float* imageData )
265+
: _w(w)
266+
, _h(h)
267+
, _img(0)
268+
{
269+
_f = _p.get_future();
270+
271+
_imageData = (unsigned char*)malloc( w*h*sizeof(float) );
272+
if( _imageData != 0 ) {
273+
memcpy( _imageData, imageData, w*h*sizeof(float) );
274+
} else {
275+
cerr << __FILE__ << ":" << __LINE__ << " Memory limitation" << endl
276+
<< "E Failed to allocate memory for SiftJob" << endl;
277+
exit( -1 );
278+
}
279+
}
280+
223281
SiftJob::~SiftJob( )
224282
{
225283
delete [] _imageData;
226284
}
227285

228-
void SiftJob::setImg( popsift::Image* img )
286+
void SiftJob::setImg( popsift::ImageBase* img )
229287
{
230288
img->resetDimensions( _w, _h );
231289
img->load( _imageData );
232290
_img = img;
233291
}
234292

235-
popsift::Image* SiftJob::getImg()
293+
popsift::ImageBase* SiftJob::getImg()
236294
{
237295
#ifdef USE_NVTX
238296
_nvtx_id = nvtxRangeStartA( "inserting image" );

src/popsift/popsift.h

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,42 @@
2929
/* user parameters */
3030
namespace popsift
3131
{
32-
class Image;
32+
class ImageBase;
3333
class Pyramid;
3434
class FeaturesBase;
3535
class FeaturesHost;
3636
class FeaturesDev;
37-
};
37+
38+
}; // namespace popsift
3839

3940
class SiftJob
4041
{
4142
std::promise<popsift::FeaturesBase*> _p;
4243
std::future <popsift::FeaturesBase*> _f;
43-
int _w;
44-
int _h;
45-
unsigned char* _imageData;
46-
popsift::Image* _img;
44+
int _w;
45+
int _h;
46+
unsigned char* _imageData;
47+
popsift::ImageBase* _img;
4748
#ifdef USE_NVTX
48-
nvtxRangeId_t _nvtx_id;
49+
nvtxRangeId_t _nvtx_id;
4950
#endif
5051

5152
public:
53+
/** Constructor for byte images, value range 0..255 */
5254
SiftJob( int w, int h, const unsigned char* imageData );
55+
56+
/** Constructor for float images, value range [0..1[ */
57+
SiftJob( int w, int h, const float* imageData );
58+
5359
~SiftJob( );
5460

5561
popsift::FeaturesHost* get(); // should be deprecated, same as getHost()
5662
popsift::FeaturesBase* getBase();
5763
popsift::FeaturesHost* getHost();
5864
popsift::FeaturesDev* getDev();
5965

60-
void setImg( popsift::Image* img );
61-
popsift::Image* getImg();
66+
void setImg( popsift::ImageBase* img );
67+
popsift::ImageBase* getImg();
6268

6369
/** fulfill the promise */
6470
void setFeatures( popsift::FeaturesBase* f );
@@ -68,22 +74,31 @@ class PopSift
6874
{
6975
struct Pipe
7076
{
71-
boost::thread* _thread_stage1;
72-
boost::thread* _thread_stage2;
73-
boost::sync_queue<SiftJob*> _queue_stage1;
74-
boost::sync_queue<SiftJob*> _queue_stage2;
75-
boost::sync_queue<popsift::Image*> _unused;
76-
popsift::Image* _current;
77-
78-
popsift::Pyramid* _pyramid;
77+
boost::thread* _thread_stage1;
78+
boost::thread* _thread_stage2;
79+
boost::sync_queue<SiftJob*> _queue_stage1;
80+
boost::sync_queue<SiftJob*> _queue_stage2;
81+
boost::sync_queue<popsift::ImageBase*> _unused;
82+
popsift::ImageBase* _current;
83+
84+
popsift::Pyramid* _pyramid;
85+
};
86+
87+
public:
88+
enum ImageMode
89+
{
90+
ByteImages,
91+
FloatImages
7992
};
8093

8194
public:
8295
/* We support more than 1 streams, but we support only one sigma and one
8396
* level parameters.
8497
*/
85-
PopSift( );
86-
PopSift( const popsift::Config& config, popsift::Config::ProcessingMode mode = popsift::Config::ExtractingMode );
98+
PopSift( ImageMode imode = ByteImages );
99+
PopSift( const popsift::Config& config,
100+
popsift::Config::ProcessingMode mode = popsift::Config::ExtractingMode,
101+
ImageMode imode = ByteImages );
87102
~PopSift();
88103

89104
public:
@@ -93,10 +108,16 @@ class PopSift
93108

94109
void uninit( );
95110

111+
/** Enqueue a byte image, value range 0..255 */
96112
SiftJob* enqueue( int w,
97113
int h,
98114
const unsigned char* imageData );
99115

116+
/** Enqueue a float image, value range 0..1 */
117+
SiftJob* enqueue( int w,
118+
int h,
119+
const float* imageData );
120+
100121
/** deprecated */
101122
inline void uninit( int /*pipe*/ ) { uninit(); }
102123

@@ -142,5 +163,6 @@ class PopSift
142163

143164
int _last_init_w; /* to support depreacted interface */
144165
int _last_init_h; /* to support depreacted interface */
166+
ImageMode _image_mode;
145167
};
146168

0 commit comments

Comments
 (0)