00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
#include <fstream>
00046
#include "RGBImage.h"
00047
#include <plearn/math/TMat_maths.h>
00048
00049
namespace PLearn {
00050
using namespace std;
00051
00052
const RGB RGB::BLACK(0,0,0);
00053
const RGB RGB::WHITE(255,255,255);
00054
const RGB RGB::RED(255,0,0);
00055
const RGB RGB::GREEN(0,255,0);
00056
const RGB RGB::BLUE(0,0,255);
00057 const RGB RGB::DISCOCOLORS[] = {RGB::RED, RGB::GREEN, RGB::BLUE};
00058
00059
00060
00061
00062
00063
00064 RGBImage::RGBImage(
int the_height,
int the_width)
00065 :height_(the_height), width_(the_width)
00066 {
00067 tmpnam(
tmpfilename);
00068
if(
height_>0 &&
width_>0)
00069 {
00070
storage =
new Storage<RGB>(
height_*
width_);
00071
clear();
00072 }
00073 }
00074
00075 RGBImage::RGBImage(
Mat r,
Mat g,
Mat b)
00076 :height_(r.length()), width_(r.width())
00077 {
00078 tmpnam(
tmpfilename);
00079
storage =
new Storage<RGB>(
height_*
width_);
00080
for(
int i=0; i<
height_; i++)
00081
for(
int j=0; j<
width_; j++)
00082
setPixel(i,j,
RGB((
unsigned char)r(i,j), (
unsigned char)g(i,j), (
unsigned char)b(i,j)));
00083 }
00084
00085
00086 RGBImage::~RGBImage()
00087 {
00088 unlink(
tmpfilename);
00089 }
00090
00091
void
00092 RGBImage::resize(
int newheight,
int newwidth)
00093 {
00094
if(
storage)
00095
storage->resize(newheight*newwidth);
00096
else
00097
storage =
new Storage<RGB>(newheight*newwidth);
00098
height_ = newheight;
00099
width_ = newwidth;
00100 }
00101
00102
void
00103 RGBImage::removeBorders(
int top_border,
int bottom_border,
00104
int left_border,
int right_border)
00105 {
00106
if(!
storage)
00107
PLERROR(
"Empty RGBImage");
00108
int newwidth =
width_ - (left_border + right_border);
00109
int newheight =
height_ - (top_border + bottom_border);
00110
if (newheight < 1)
00111
PLERROR(
"RGBImage::removeBorders(%d,%d,%d,%d): can't remove more than height_(%d)",
00112 top_border,bottom_border,left_border,right_border,
height_);
00113
if (newwidth < 1)
00114
PLERROR(
"RGBImage::removeBorders(%d,%d,%d,%d): can't remove more than width_(%d)",
00115 top_border,bottom_border,left_border,right_border,
width_);
00116
PP< Storage<RGB> > newstorage =
new Storage<RGB>(newheight*newwidth);
00117
RGB* d= newstorage->data;
00118
RGB* data =
storage->data;
00119
for (
int r=0;r<newheight;r++)
00120
for (
int c=0;c<newwidth;c++,d++)
00121 *d = data[(top_border+r)*
width_+(left_border+c)];
00122
height_=newheight;
00123
width_=newwidth;
00124
storage = newstorage;
00125 }
00126
00127
void
00128 RGBImage::fill(
RGB color)
00129 {
00130
if(!
storage)
00131
PLERROR(
"Empty RGBImage");
00132
RGB* data =
storage->data;
00133
for(
int pos=0; pos<
height_*
width_; pos++)
00134 data[pos] =
color;
00135 }
00136
00137
void
00138 RGBImage::loadPPM(
const char* filename)
00139 {
00140
int ncolors;
00141 ifstream in(filename);
00142
if(!in)
00143
PLERROR(
"In RGBImage::loadPPM could not open file %s for reading",filename);
00144
00145
char imagetype[20];
00146
int newheight, newwidth;
00147 in >> imagetype >> newwidth >> newheight >> ncolors;
00148
char tmp[100];
00149 in.getline(tmp,99);
00150
if(strcmp(imagetype,
"P6")!=0)
00151
PLERROR(
"In RGBImage::loadPPM unsupported format (not a P6 PPM)");
00152
resize(newheight, newwidth);
00153
RGB* data =
storage->data;
00154
PLWARNING(
"In RGBImage::loadPPM - Code has been changed to compile, but hasn't been tested (remove this warning if it works)");
00155
00156
00157
00158 in.read((
char*)data,
height_*
width_*3);
00159 }
00160
00161
void
00162 RGBImage::savePPM(
const char* filename)
const
00163
{
00164
if(!
storage)
00165
PLERROR(
"Empty RGBImage");
00166
RGB* data =
storage->data;
00167 ofstream out(filename);
00168
if(!out)
00169
PLERROR(
"In RGBImage::savePPM could not open file for writing");
00170 out <<
"P6\n" <<
width_ <<
' ' <<
height_ <<
' ' << 255 <<
endl;
00171
PLWARNING(
"In RGBImage::loadPPM - Code has been changed to compile, but hasn't been tested (remove this warning if it works)");
00172
00173
00174
00175 out.write((
char*)data,
height_*
width_*3);
00176 out.flush();
00177 }
00178
00179
void
00180 RGBImage::display()
const
00181
{
00182
savePPM(
tmpfilename);
00183
char command[1000];
00184 sprintf(command,
"xv %s &",
tmpfilename);
00185 system(command);
00186 }
00187
00188
void
00189 RGBImage::loadJPEG(
const char* filename,
int scale)
00190 {
00191
char command[1000];
00192 sprintf(command,
"djpeg -pnm -scale 1/%d %s > %s", scale, filename,
tmpfilename);
00193 system(command);
00194 cout << command <<
endl;
00195
loadPPM(
tmpfilename);
00196 unlink(
tmpfilename);
00197 }
00198
00199
void
00200 RGBImage::displayAndWait()
const
00201
{
00202
savePPM(
tmpfilename);
00203
char command[1000];
00204 sprintf(command,
"xv %s",
tmpfilename);
00205 system(command);
00206 unlink(
tmpfilename);
00207 }
00208
00209
void
00210 RGBImage::shrinkToIntersection(
int& i,
int& j,
int& h,
int& w)
const
00211
{
00212
int istart =
MAX(0,i);
00213
int iend =
MIN(i+h,
height_);
00214
int jstart =
MAX(0,j);
00215
int jend =
MIN(j+w,
width_);
00216
00217 i = istart;
00218 j = jstart;
00219 h =
MAX(iend-istart,0);
00220 w =
MAX(jend-jstart,0);
00221 }
00222
00223
void
00224 RGBImage::blit(
int desti,
int destj,
const RGBImage srcim)
00225 {
00226
int blit_i = desti;
00227
int blit_j = destj;
00228
int blit_h = srcim.
height_;
00229
int blit_w = srcim.
width_;
00230
00231
shrinkToIntersection(blit_i,blit_j,blit_h,blit_w);
00232
if(blit_h==0 || blit_w==0)
00233
return;
00234
00235
int src_i = blit_i-desti;
00236
int src_j = blit_j-destj;
00237
00238
for(
int i=0; i<blit_h; i++)
00239
for(
int j=0; j<blit_w; j++)
00240
setPixel(blit_i+i, blit_j+j, srcim.
getPixel(src_i+i,src_j+j));
00241 }
00242
00243
RGB
00244 RGBImage::computeAverage()
const
00245
{
00246
if(!
storage)
00247
PLERROR(
"Empty RGBImage");
00248
RGB* data =
storage->data;
00249
int r = 0;
00250
int g = 0;
00251
int b = 0;
00252
int npixels =
height_*
width_;
00253
for(
int pos=0; pos<npixels; pos++)
00254 {
00255
RGB& pixl = data[pos];
00256 r += pixl.
r;
00257 g += pixl.
g;
00258 b += pixl.
b;
00259 }
00260
return RGB(r/npixels, g/npixels, b/npixels);
00261 }
00262
00263
Vec
00264 RGBImage::computeHistogram(
int r_bins,
int g_bins,
int b_bins,
bool do_normalize)
00265 {
00266
Vec histo(r_bins*g_bins*b_bins);
00267
for(
int i=0; i<
height_; i++)
00268
for(
int j=0; j<
width_; j++)
00269 {
00270
RGB pix =
getPixel(i,j);
00271
int r_bin = pix.
r*r_bins/256;
00272
int g_bin = pix.
g*g_bins/256;
00273
int b_bin = pix.
b*b_bins/256;
00274
int pos = r_bin*g_bins*b_bins + g_bin*b_bins + b_bin;
00275 histo[pos]++;
00276 }
00277
if(do_normalize)
00278 histo /= height_*width_;
00279
return histo;
00280 }
00281
00282
00283
00284
00285
00286 RGBImageDB::RGBImageDB(
int the_subsample_factor,
int the_remove_border,
int the_max_n_images_in_memory)
00287 : subsample_factor(the_subsample_factor), remove_border(the_remove_border),
00288 max_n_images_in_memory(the_max_n_images_in_memory), n_images_in_memory(0)
00289 {
00290 }
00291
00292 RGBImageDB::RGBImageDB(
char* dbfilename,
int the_subsample_factor,
int the_remove_border,
int the_max_n_images_in_memory)
00293 : subsample_factor(the_subsample_factor), remove_border(the_remove_border),
00294 max_n_images_in_memory(the_max_n_images_in_memory), n_images_in_memory(0)
00295 {
00296
load(dbfilename);
00297 }
00298
00299
void
00300 RGBImageDB::load(
char* dbfile)
00301 {
00302 ifstream in(dbfile);
00303
if(!in)
00304
PLERROR(
"In RGBImageDB::load could not open dbfile %s for reading",dbfile);
00305
00306
char filename[300];
00307
int classnum;
00308
00309
int n = 0;
00310 in >> filename >> classnum;
00311
while(in)
00312 {
00313
int imageid =
append(filename);
00314 n++;
00315
imageIdAndClass.
resize(n,2);
00316
imageIdAndClass(n-1,0) = imageid;
00317
imageIdAndClass(n-1,1) = classnum;
00318 in >> filename >> classnum;
00319 }
00320 }
00321
00322
int
00323 RGBImageDB::append(
char* filename)
00324 {
00325
filenames.
append(strdup(filename));
00326
images.
append(0);
00327
return filenames.
size()-1;
00328 }
00329
00330
RGBImage
00331 RGBImageDB::getImage(
int imageid)
00332 {
00333
if(!
images[imageid])
00334 {
00335
RGBImage* newimage =
new RGBImage;
00336 newimage->
loadJPEG(
filenames[imageid],
subsample_factor);
00337
if (
remove_border>0)
00338 newimage->
removeBorders(
remove_border);
00339
n_images_in_memory++;
00340
if (
n_images_in_memory>
max_n_images_in_memory)
00341 {
00342
for(
int i=0; i<
images.
size(); i++)
00343
if(
images[i]!=0)
00344 {
00345
delete images[i];
00346
images[i] = 0;
00347 }
00348 }
00349
images[imageid] = newimage;
00350 }
00351
return *
images[imageid];
00352 }
00353
00354
00355
Mat
00356 RGBImageDB::computeHistogramRepresentation(
int r_bins,
int g_bins,
int b_bins,
bool do_normalize)
00357 {
00358
Mat dataset(
imageIdAndClass.
length(), r_bins*g_bins*b_bins+1);
00359
Mat histograms = dataset.
subMatColumns(0,r_bins*g_bins*b_bins);
00360
Mat classnums = dataset.
lastColumn();
00361
00362
for(
int i=0; i<
imageIdAndClass.
length(); i++)
00363 {
00364
RGBImage im =
getImage((
int)
imageIdAndClass(i,0));
00365 histograms(i) << im.
computeHistogram(r_bins,g_bins,b_bins,do_normalize);
00366 classnums(i,0) =
imageIdAndClass(i,0);
00367 }
00368
return dataset;
00369 }
00370
00371
00372 RGBImageDB::~RGBImageDB()
00373 {
00374
for(
int i=0; i<
filenames.
size(); i++)
00375 {
00376 free(
filenames[i]);
00377
if(
images[i])
00378
delete images[i];
00379 }
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 RGBImageVMatrix::
00390 RGBImageVMatrix(
RGBImage the_image,
00391
const Vec& drow,
const Vec& dcol,
00392
real the_scale,
00393
real the_offset)
00394 :image(the_image),
00395 delta_row(drow), delta_column(dcol),
00396 scale(the_scale), offset_(the_offset)
00397 {
00398
if (
delta_row.
length()!=
delta_column.
length())
00399
PLERROR(
"RGBImageVMatrix: delta_row(%d) and delta_column(%d) have"
00400
" differing sizes",
delta_row.
length(),
delta_column.
length());
00401
width_ = 3 * (
delta_row.
length() + 1);
00402
if (
delta_row.
length()>0)
00403 {
00404
max_delta_row = (
int)
max(
delta_row);
00405
int min_delta_row = (
int)
min(
delta_row);
00406
max_delta_column = (
int)
max(
delta_column);
00407
int min_delta_column = (
int)
min(
delta_column);
00408
first_row =
MAX(0,-min_delta_row);
00409
first_column =
MAX(0,-min_delta_column);
00410
bottom_border_row =
MIN(
image.
height(),
image.
height()-
max_delta_row);
00411
right_border_col =
MIN(
image.
width(),
image.
width()-
max_delta_column);
00412 }
00413
else
00414 {
00415
first_row = 0;
00416
first_column = 0;
00417
bottom_border_row =
image.
height();
00418
right_border_col =
image.
width();
00419 }
00420
n_cols =
right_border_col -
first_column;
00421
reset();
00422 }
00423
00424 void RGBImageVMatrix::setImage(
RGBImage new_image)
00425 {
00426
image = new_image;
00427
if (
delta_row.
length()>0)
00428 {
00429
bottom_border_row =
00430
MIN(
image.
height(),
image.
height()-
max_delta_row);
00431
right_border_col =
00432
MIN(
image.
width(),
image.
width()-
max_delta_column);
00433 }
00434
else
00435 {
00436
bottom_border_row =
image.
height();
00437
right_border_col =
image.
width();
00438 }
00439
n_cols =
right_border_col -
first_column;
00440
reset();
00441 }
00442
00443 int RGBImageVMatrix::length()
00444 {
return (
bottom_border_row-
first_row)*
n_cols; }
00445
00446 int RGBImageVMatrix::width()
00447 {
return width_; }
00448
00449 void RGBImageVMatrix::reset()
00450 {
00451
current_i=
first_row;
00452
current_j=
first_column;
00453 }
00454
00455 void RGBImageVMatrix::seek(
int position)
00456 {
00457
if (position>=
length())
00458
PLERROR(
"RGBImageVMatrix::seek(%d > size=%d)",position,
length());
00459
int i = position /
n_cols;
00460
current_i =
first_row + i;
00461
current_j =
first_column + position - i*
n_cols;
00462 }
00463
00464 int RGBImageVMatrix::position()
00465 {
00466
return (
current_j-
first_column) + (
current_i-
first_row)*
n_cols;
00467 }
00468
00469 void RGBImageVMatrix::sample(
Vec& samplevec)
00470 {
00471 samplevec.
resize(
width_);
00472
real *
sample = samplevec.
data();
00473
real *dr =
delta_row.
data();
00474
real *dc =
delta_column.
data();
00475
int np =
delta_row.
length();
00476
00477
for (
int p=0; p<np; p++) {
00478
int offset_i=(
int)dr[p];
00479
int offset_j=(
int)dc[p];
00480
RGB parent_rgb =
image.
getPixel(
current_i+offset_i,
current_j+offset_j);
00481 *(
sample++) = (parent_rgb.
r+
offset_)*
scale;
00482 *(
sample++) = (parent_rgb.
g+
offset_)*
scale;
00483 *(
sample++) = (parent_rgb.
b+
offset_)*
scale;
00484 }
00485
00486
00487
RGB target_rgb =
image.
getPixel(
current_i,
current_j);
00488 *(
sample++) = (target_rgb.
r+
offset_)*
scale;
00489 *(
sample++) = (target_rgb.
g+
offset_)*
scale;
00490 *(
sample++) = (target_rgb.
b+
offset_)*
scale;
00491
00492
00493
00494
current_j++;
00495
if (
current_j==
right_border_col)
00496 {
00497
current_j =
first_column;
00498
current_i++;
00499
if (
current_i==
bottom_border_row)
00500
current_i =
first_row;
00501 }
00502 }
00503
00504
00505
00506
00507
00508 RGBImagesVMatrix::
00509 RGBImagesVMatrix(
RGBImageDB& imagesdb,
00510
const Vec& delta_row,
00511
const Vec& delta_col,
00512
bool appendclass,
00513
real scale,
00514
real offset_)
00515 :image_distr(imagesdb.getImage((
int)imagesdb.imageIdAndClass(0,0)),delta_row,delta_col,scale,offset_),
00516 images_db(imagesdb), current_image(0), append_class(appendclass),
00517 length_(0), image_start(imagesdb.imageIdAndClass.length())
00518 {
00519
width_ = 3*(delta_row.
length()+1);
00520
if(
append_class)
00521
width_++;
00522
00523
for (
int i=0;i<
images_db.
imageIdAndClass.
length();i++)
00524 {
00525
image_start[i] =
length_;
00526
image_distr.
setImage(
images_db.
getImage((
int)imagesdb.
imageIdAndClass(i,0)));
00527 length_ +=
image_distr.
length();
00528 }
00529
if (
append_class)
00530 {
00531
int n =
image_distr.
width();
00532
pixelsAndClass.
resize(n+1);
00533
pixels =
pixelsAndClass.
subVec(0,n);
00534 }
00535 }
00536
00537 int RGBImagesVMatrix::length()
00538 {
return length_; }
00539
00540 int RGBImagesVMatrix::width()
00541 {
return width_; }
00542
00543 void RGBImagesVMatrix::reset()
00544 {
00545
current_image = 0;
00546
image_distr.
setImage(
images_db.
getImage((
int)
images_db.
imageIdAndClass(0,0)));
00547
image_distr.
reset();
00548 }
00549
00550 void RGBImagesVMatrix::sample(
Vec& samplevec)
00551 {
00552 samplevec.
resize(
width_);
00553
if (
append_class)
00554 {
00555
Vec tmpvec = samplevec.
subVec(0,
width_-1);
00556
image_distr.
sample(tmpvec);
00557 samplevec[
width_-1] =
images_db.
imageIdAndClass(
current_image,1);
00558 }
00559
else
00560
image_distr.
sample(samplevec);
00561
00562
if (
image_distr.
first())
00563 {
00564
current_image++;
00565
if (
current_image ==
images_db.
imageIdAndClass.
length())
00566
current_image = 0;
00567
image_distr.
setImage(
images_db.
getImage((
int)
images_db.
imageIdAndClass(
current_image,0)));
00568 }
00569 }
00570
00571
00572 void RGBImagesVMatrix::seek(
int position)
00573 {
00574
int n=
images_db.
imageIdAndClass.
length();
00575
int i;
00576
for (i=0;i<n && position>=
image_start[i];i++);
00577
current_image = i-1;
00578
image_distr.
setImage(
images_db.
getImage((
int)
images_db.
imageIdAndClass(
current_image,0)));
00579
image_distr.
seek(
int(position-image_start[current_image]));
00580 }
00581
00582
00583 int RGBImagesVMatrix::position()
00584 {
00585
return (
int)
image_start[
current_image] +
image_distr.
position();
00586 }
00587
00588 bool RGBImagesVMatrix::firstSampleOfObject()
00589 {
00590
return image_distr.
first();
00591 }
00592
00593 int RGBImagesVMatrix::nSamplesOfObject()
00594 {
00595
return image_distr.
length();
00596 }
00597
00598
00599 int RGBImagesVMatrix::nObjects()
00600 {
00601
return images_db.
imageIdAndClass.
length();
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 }