Commit c25e7d0d7c5ce33f99b99126de0fd426be193ec1

Authored by heziqi
1 parent 6dbb23ce

speed of bip.baseline fixed

Showing 3 changed files with 403 additions and 13 deletions   Show diff stats
envi/bil.h
  1 +#include "../envi/envi.h"
  2 +#include "../envi/binary.h"
  3 +#include <cstring>
  4 +#include <utility>
  5 +
  6 +namespace rts{
  7 +
  8 +template <typename T>
  9 +
  10 +class bil: public binary<T> {
  11 +
  12 +protected:
  13 +
  14 + envi header;
  15 +
  16 +public:
  17 +
  18 + using binary<T>::open;
  19 + using binary<T>::file;
  20 + using binary<T>::getSlice;
  21 +
  22 + //open a file, given the file and its header's names
  23 + bool open(std::string filename, std::string headername){
  24 +
  25 + if (header.load(headername)==false){
  26 + std::cout<<"ERROR: unable to load header file: "<<headername<<std::endl;
  27 + return false;
  28 + }
  29 +
  30 + open(filename, vec<unsigned int>(header.samples, header.lines, header.bands), header.header_offset);
  31 + return true;
  32 +
  33 + }
  34 +
  35 + //save one band of the file into the memory, and return the pointer
  36 + bool band_index( T * p, unsigned int page){
  37 +
  38 + unsigned int L = header.samples * sizeof(T); //caculate the number of bytes in a sample line
  39 + unsigned int jump = header.samples * (header.bands - 1) * sizeof(T);
  40 +
  41 + if (page >= header.bands){ //make sure the bank number is right
  42 + std::cout<<"ERROR: page out of range"<<std::endl;
  43 + return false;
  44 + }
  45 +
  46 + file.seekg(header.samples * page * sizeof(T), std::ios::beg);
  47 + for (unsigned i = 0; i < header.lines; i++)
  48 + {
  49 + file.read((char *)(p + i * header.samples), L);
  50 + file.seekg( jump, std::ios::cur);
  51 + }
  52 +
  53 + return true;
  54 + }
  55 +
  56 + bool getBand( T * p, double wavelength){
  57 +
  58 + unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band
  59 + unsigned int S = XY * sizeof(T); //calculate the number of bytes of a band
  60 +
  61 + unsigned page=0; //bands around the wavelength
  62 + T * p1;
  63 + T * p2;
  64 +
  65 + //get the bands numbers around the wavelength
  66 +
  67 + //if wavelength is smaller than the first one in header file
  68 + if ( header.wavelength[page] > wavelength ){
  69 + band_index(p, page);
  70 + return true;
  71 + }
  72 +
  73 + while( header.wavelength[page] < wavelength )
  74 + {
  75 + page++;
  76 + //if wavelength is larger than the last wavelength in header file
  77 + if (page == header.bands) {
  78 + band_index(p, header.bands-1);
  79 + return true;
  80 + }
  81 + }
  82 + if ( wavelength < header.wavelength[page] )
  83 + {
  84 + p1=(T*)malloc(S); //memory allocation
  85 + p2=(T*)malloc(S);
  86 + band_index(p1, page - 1);
  87 + band_index(p2, page );
  88 + for(unsigned i=0; i < XY; i++){
  89 + double r = (double) (wavelength - header.wavelength[page-1]) / (double) (header.wavelength[page] - header.wavelength[page-1]);
  90 + p[i] = (p2[i] - p1[i]) * r + p1[i];
  91 + }
  92 + }
  93 + else //if the wavelength is equal to a wavelength in header file
  94 + {
  95 + band_index(p, page);
  96 + }
  97 +
  98 + return true;
  99 + }
  100 +
  101 + //get YZ line from the a Y slice, Y slice data should be already IN the MEMORY
  102 + bool getYZ(T* p, T* c, double wavelength)
  103 + {
  104 + unsigned int X = header.samples; //calculate the number of pixels in a sample
  105 + unsigned int B = header.bands;
  106 + unsigned int L = X * sizeof(T);
  107 +
  108 + unsigned page=0; //samples around the wavelength
  109 + T * p1;
  110 + T * p2;
  111 +
  112 + //get the bands numbers around the wavelength
  113 +
  114 + //if wavelength is smaller than the first one in header file
  115 + if ( header.wavelength[page] > wavelength ){
  116 + memcpy(p, c, L);
  117 + return true;
  118 + }
  119 +
  120 + while( header.wavelength[page] < wavelength )
  121 + {
  122 + page++;
  123 + //if wavelength is larger than the last wavelength in header file
  124 + if (page == B) {
  125 + memcpy(p, c + (B - 1) * X, L);
  126 + return true;
  127 + }
  128 + }
  129 + if ( wavelength < header.wavelength[page] )
  130 + {
  131 + p1=(T*)malloc( L ); //memory allocation
  132 + p2=(T*)malloc( L );
  133 +
  134 + memcpy(p1, c + (page - 1) * X, L);
  135 + memcpy(p2, c + page * X, L);
  136 +
  137 + for(unsigned i=0; i < X; i++){
  138 + double r = (double) (wavelength - header.wavelength[page-1]) / (double) (header.wavelength[page] - header.wavelength[page-1]);
  139 + p[i] = (p2[i] - p1[i]) * r + p1[i];
  140 + }
  141 + }
  142 + else //if the wavelength is equal to a wavelength in header file
  143 + memcpy(p, c + page * X, L);
  144 +
  145 + return true;
  146 + }
  147 +
  148 + //save one pixel of the BIP file into the memory, and return the pointer
  149 + bool getSpectrum(T * p, unsigned x, unsigned y){
  150 +
  151 + if ( x >= header.samples || y >= header.lines){ //make sure the sample and line number is right
  152 + std::cout<<"ERROR: sample or line out of range"<<std::endl;
  153 + exit(1);
  154 + }
  155 +
  156 + unsigned jump = (header.samples - 1) * sizeof(T);
  157 +
  158 + file.seekg((y * header.samples * header.bands + x) * sizeof(T), std::ios::beg);
  159 +
  160 + for(unsigned i = 0; i < header.bands; i++)
  161 + { //point to the certain sample and line
  162 + file.read((char *)(p + i), sizeof(T));
  163 + file.seekg(jump, std::ios::cur);
  164 + }
  165 +
  166 + return true;
  167 + }
  168 +
  169 + //given a Y ,return a XZ slice
  170 + bool getY(T * p, unsigned y)
  171 + {
  172 + if ( y >= header.lines){ //make sure the line number is right
  173 + std::cout<<"ERROR: line out of range"<<std::endl;
  174 + exit(1);
  175 + }
  176 +
  177 + file.seekg(y * header.bands * header.samples * sizeof(T), std::ios::beg);
  178 + file.read((char *)p, sizeof(T) * header.bands * header.samples);
  179 +
  180 + return true;
  181 +
  182 + }
  183 +
  184 + //(BIL) baseline correction
  185 + bool baseline(std::string outname, std::vector<double> wls){
  186 +
  187 + unsigned N = wls.size(); //get the number of baseline points
  188 +
  189 + std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
  190 + std::string headername = outname + ".hdr"; //the header file name
  191 +
  192 + //simplify image resolution
  193 + unsigned int ZX = header.bands * header.samples; //calculate the number of points in a Y slice
  194 + unsigned int L = ZX * sizeof(T); //calculate the number of bytes of a Y slice
  195 + unsigned int B = header.bands;
  196 + unsigned int X = header.samples;
  197 +
  198 + T* c; //pointer to the current Y slice
  199 + c = (T*)malloc(L); //memory allocation
  200 +
  201 + T* a; //pointer to the two YZ lines surrounding the current YZ line
  202 + T* b;
  203 +
  204 + a = (T*)malloc(X * sizeof(T));
  205 + b = (T*)malloc(X * sizeof(T));
  206 +
  207 +
  208 + double ai, bi; //stores the two baseline points wavelength surrounding the current band
  209 + double ci; //stores the current band's wavelength
  210 + unsigned control=0;
  211 +
  212 + if (a == NULL || b == NULL || c == NULL){
  213 + std::cout<<"ERROR: error allocating memory";
  214 + exit(1);
  215 + }
  216 + // loop start correct every y slice
  217 +
  218 + for (unsigned k =0; k < header.lines; k++)
  219 + {
  220 + //get the current y slice
  221 + getY(c, k);
  222 +
  223 + //initialize lownum, highnum, low, high
  224 + ai = header.wavelength[0];
  225 + //if no baseline point is specified at band 0,
  226 + //set the baseline point at band 0 to 0
  227 + if(wls[0] != header.wavelength[0]){
  228 + bi = wls[control];
  229 + memset(a, (char)0, X * sizeof(T) );
  230 + }
  231 + //else get the low band
  232 + else{
  233 + control++;
  234 + getYZ(a, c, ai);
  235 + bi = wls[control];
  236 + }
  237 + //get the high band
  238 + getYZ(b, c, bi);
  239 +
  240 + //correct every YZ line
  241 +
  242 + for(unsigned cii = 0; cii < B; cii++){
  243 +
  244 + //update baseline points, if necessary
  245 + if( header.wavelength[cii] >= bi && cii != B - 1) {
  246 + //if the high band is now on the last BL point
  247 + if (control != N-1) {
  248 +
  249 + control++; //increment the index
  250 +
  251 + std::swap(a, b); //swap the baseline band pointers
  252 +
  253 + ai = bi;
  254 + bi = wls[control];
  255 + getYZ(b, c, bi);
  256 +
  257 + }
  258 + //if the last BL point on the last band of the file?
  259 + else if ( wls[control] < header.wavelength[B - 1]) {
  260 +
  261 + std::swap(a, b); //swap the baseline band pointers
  262 +
  263 + memset(b, (char)0, X * sizeof(T) ); //clear the high band
  264 +
  265 + ai = bi;
  266 + bi = header.wavelength[B - 1];
  267 + }
  268 + }
  269 +
  270 + //get the current YZ line
  271 + //band_index(c, cii);???????????????????????????????????
  272 + /*
  273 + file.seekg( (k * header.bands * X + cii)* sizeof(T), std::ios::beg);
  274 + for(unsigned j = 0; j < X; j++)
  275 + {
  276 + file.read((char *)(c + j), sizeof(T));
  277 + file.seekg((B - 1) * sizeof(T), std::ios::cur);
  278 + }*/
  279 +
  280 + ci = header.wavelength[cii];
  281 +
  282 + unsigned jump = cii * X;
  283 + //perform the baseline correction
  284 + for(unsigned i=0; i < X; i++)
  285 + {
  286 + double r = (double) (ci - ai) / (double) (bi - ai);
  287 + c[i + jump] =(float) ( c[i + jump] - (b[i] - a[i]) * r - a[i] );
  288 + }
  289 +
  290 + }//loop for YZ line end
  291 + std::cout<<k<<std::endl;
  292 + target.write(reinterpret_cast<const char*>(c), L); //write the corrected data into destination
  293 + }//loop for Y slice end
  294 +
  295 + header.save(headername); //save the new header file
  296 +
  297 + free(a);
  298 + free(b);
  299 + free(c);
  300 + target.close();
  301 + return true;
  302 +
  303 + }
  304 +
  305 + // normalize the BIP file
  306 + bool normalize(std::string outname, double band)
  307 + {
  308 + unsigned int B = header.bands; //calculate the number of bands
  309 + unsigned int Y = header.lines;
  310 + unsigned int X = header.samples;
  311 + unsigned int ZX = header.bands * header.samples;
  312 + unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band
  313 + unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
  314 + unsigned int L = ZX * sizeof(T);
  315 +
  316 + std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
  317 + std::string headername = outname + ".hdr"; //the header file name
  318 +
  319 + T * c; //pointer to the current ZX slice
  320 + T * b; //pointer to the standard band
  321 +
  322 + b = (T*)malloc( S ); //memory allocation
  323 + c = (T*)malloc( L );
  324 +
  325 + getBand(b, band); //get the certain band into memory
  326 +
  327 + for(unsigned j = 0; j < Y; j++)
  328 + {
  329 + getY(c, j);
  330 + for(unsigned i = 0; i < X; i++)
  331 + {
  332 + for(unsigned m = 0; m < B; m++)
  333 + {
  334 + c[m + i * B] = c[m + i * B] / b[i + j * X];
  335 + }
  336 + }
  337 + target.write(reinterpret_cast<const char*>(c), L); //write normalized data into destination
  338 + }
  339 + header.save(headername); //save the new header file
  340 +
  341 + free(b);
  342 + free(c);
  343 + target.close();
  344 + return true;
  345 + }
  346 +
  347 + //convert BIP file to BSQ file and save it
  348 + bool bsq(std::string outname)
  349 + {
  350 + unsigned int S = header.samples * header.lines * sizeof(T); //calculate the number of bytes in a band
  351 +
  352 + std::ofstream target(outname.c_str(), std::ios::binary);
  353 + std::string headername = outname + ".hdr";
  354 +
  355 + T * p; //pointer to the current band
  356 + p = (T*)malloc(S);
  357 +
  358 + for ( unsigned i = 0; i < header.bands; i++)
  359 + {
  360 + band_index(p, i);
  361 + target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file
  362 + }
  363 + header.interleave = rts::envi::interleaveType::BSQ; //change the type of file in header file
  364 + header.save(headername);
  365 +
  366 + free(p);
  367 + target.close();
  368 + return true;
  369 + }
  370 +
  371 + };
  372 +}
0 373 \ No newline at end of file
... ...
envi/bip.h
... ... @@ -241,8 +241,6 @@ public:
241 241 //I have not used it so far
242 242 bool getSpectrum(T * p, unsigned x, unsigned y){
243 243  
244   - unsigned int i;
245   -
246 244 if ( x >= header.samples || y >= header.lines){ //make sure the sample and line number is right
247 245 std::cout<<"ERROR: sample or line out of range"<<std::endl;
248 246 exit(1);
... ... @@ -271,7 +269,6 @@ public:
271 269 }
272 270  
273 271 //(BIP) baseline correction
274   - //processing speed is too slow
275 272 bool baseline(std::string outname, std::vector<double> wls){
276 273  
277 274 unsigned N = wls.size(); //get the number of baseline points
... ... @@ -357,15 +354,6 @@ public:
357 354 }
358 355 }
359 356  
360   - //get the current YZ line
361   - //band_index(c, cii);
362   - file.seekg( (k * header.bands * X + cii)* sizeof(T), std::ios::beg);
363   - for(unsigned j = 0; j < X; j++)
364   - {
365   - file.read((char *)(c + j), sizeof(T));
366   - file.seekg((B - 1) * sizeof(T), std::ios::cur);
367   - }
368   -
369 357 ci = header.wavelength[cii];
370 358  
371 359 //perform the baseline correction
... ... @@ -376,7 +364,6 @@ public:
376 364 }
377 365  
378 366 }//loop for YZ line end
379   -
380 367 target.write(reinterpret_cast<const char*>(c), L); //write the corrected data into destination
381 368 }//loop for Y slice end
382 369  
... ...
envi/bsq.h
... ... @@ -275,6 +275,37 @@ public:
275 275 target.close();
276 276 return true;
277 277 }
  278 +
  279 + //convert BSQ file to BIL file and save it
  280 + bool bil(std::string outname)
  281 + {
  282 + //simplify image resolution
  283 + unsigned int L = header.samples * header.bands * sizeof(T); //calculate the number of bytes of a ZX slice
  284 + unsigned int jump = (header.lines - 1) * header.samples * sizeof(T);
  285 +
  286 + std::ofstream target(outname.c_str(), std::ios::binary);
  287 + std::string headername = outname + ".hdr";
  288 +
  289 + T * p; //pointer to the current spectrum
  290 + p = (T*)malloc(L);
  291 +
  292 + for ( unsigned i = 0; i < header.lines; i++)
  293 + {
  294 + file.seekg(header.samples * i * sizeof(T), std::ios::beg);
  295 + for ( unsigned j = 0; j < header.bands; j++ )
  296 + {
  297 + file.read((char *)(p + j * header.samples), sizeof(T) * header.samples);
  298 + file.seekg(jump, std::ios::cur); //go to the next band
  299 + }
  300 + target.write(reinterpret_cast<const char*>(p), L); //write XZ slice data into target file
  301 + }
  302 + header.interleave = rts::envi::interleaveType::BIL; //change the type of file in header file
  303 + header.save(headername);
  304 +
  305 + free(p);
  306 + target.close();
  307 + return true;
  308 + }
278 309  
279 310  
280 311 };
... ...