Commit dc8eb8aa7ab000475a4728408c5a69f1e5540e96
1 parent
6a46c8ff
added band trimming to ENVI objects
Showing
5 changed files
with
216 additions
and
0 deletions
Show diff stats
stim/envi/bil.h
@@ -1098,6 +1098,35 @@ public: | @@ -1098,6 +1098,35 @@ public: | ||
1098 | return true; | 1098 | return true; |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | + /// Remove a list of bands from the ENVI file | ||
1102 | + | ||
1103 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | ||
1104 | + /// @param b is an array of bands to be eliminated | ||
1105 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | ||
1106 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1107 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | ||
1108 | + | ||
1109 | + size_t Xb = X() * sizeof(T); //calculate the number of bytes in a line | ||
1110 | + T* line = (T*)malloc(Xb); //allocate space for a line | ||
1111 | + | ||
1112 | + size_t i; //create an index into the band array | ||
1113 | + for(size_t y = 0; y < Y(); y++){ //for each Y plane | ||
1114 | + i = 0; | ||
1115 | + for(size_t b = 0; b < Z(); b++){ //for each band | ||
1116 | + if(b != band_array[i]){ //if this band isn't trimmed | ||
1117 | + file.read((char*)line, Xb); //read a line | ||
1118 | + out.write((char*)line, Xb); //write the line | ||
1119 | + } | ||
1120 | + else{ | ||
1121 | + file.seekg(Xb, std::ios::cur); //if this band is trimmed, skip it | ||
1122 | + i++; | ||
1123 | + } | ||
1124 | + } | ||
1125 | + if(PROGRESS) progress = (double)(y+1) / (double)Y() * 100; | ||
1126 | + } | ||
1127 | + free(line); | ||
1128 | + } | ||
1129 | + | ||
1101 | 1130 | ||
1102 | /// Close the file. | 1131 | /// Close the file. |
1103 | bool close(){ | 1132 | bool close(){ |
stim/envi/bip.h
@@ -1179,6 +1179,43 @@ public: | @@ -1179,6 +1179,43 @@ public: | ||
1179 | return true; | 1179 | return true; |
1180 | } | 1180 | } |
1181 | 1181 | ||
1182 | + /// Remove a list of bands from the ENVI file | ||
1183 | + | ||
1184 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | ||
1185 | + /// @param b is an array of bands to be eliminated | ||
1186 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | ||
1187 | + | ||
1188 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1189 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | ||
1190 | + | ||
1191 | + size_t B = Z(); //calculate the number of elements in a spectrum | ||
1192 | + size_t Bdst = Z() - band_array.size(); //calculate the number of elements in an output spectrum | ||
1193 | + size_t Bb = B * sizeof(T); //calculate the number of bytes in a spectrum | ||
1194 | + size_t XY = X() * Y(); //calculate the number of pixels in the image | ||
1195 | + T* src = (T*)malloc(Bb); //allocate space to store an input spectrum | ||
1196 | + T* dst = (T*)malloc(Bdst * sizeof(T)); //allocate space to store an output spectrum | ||
1197 | + | ||
1198 | + size_t i; //index into the band array | ||
1199 | + size_t bdst; //index into the output array | ||
1200 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | ||
1201 | + i = 0; | ||
1202 | + bdst = 0; | ||
1203 | + file.read((char*)src, Bb); //read a spectrum | ||
1204 | + for(size_t b = 0; b < B; b++){ //for each band | ||
1205 | + if(b != band_array[i]){ //if the band isn't trimmed | ||
1206 | + dst[bdst] = src[b]; //copy the band value to the output spectrum | ||
1207 | + bdst++; | ||
1208 | + } | ||
1209 | + else i++; //otherwise increment i | ||
1210 | + } | ||
1211 | + out.write((char*)dst, Bdst * sizeof(T)); //write the output spectrum | ||
1212 | + if(PROGRESS) progress = (double)(xy + 1) / (double) XY * 100; | ||
1213 | + } | ||
1214 | + free(src); | ||
1215 | + free(dst); | ||
1216 | + } | ||
1217 | + | ||
1218 | + | ||
1182 | 1219 | ||
1183 | /// Close the file. | 1220 | /// Close the file. |
1184 | bool close(){ | 1221 | bool close(){ |
stim/envi/bsq.h
@@ -996,6 +996,35 @@ public: | @@ -996,6 +996,35 @@ public: | ||
996 | return true; | 996 | return true; |
997 | } | 997 | } |
998 | 998 | ||
999 | + /// Remove a list of bands from the ENVI file | ||
1000 | + | ||
1001 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | ||
1002 | + /// @param b is an array of bands to be eliminated | ||
1003 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | ||
1004 | + | ||
1005 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | ||
1006 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | ||
1007 | + | ||
1008 | + size_t XY = X() * Y(); //calculate the number of elements in a band | ||
1009 | + size_t XYb = XY * sizeof(T); //calculate the number of bytes in a band | ||
1010 | + T* temp = (T*)malloc(XYb); //allocate space to store a band | ||
1011 | + | ||
1012 | + size_t i = 0; //store the first index into the band array | ||
1013 | + | ||
1014 | + for(size_t b = 0; b < Z(); b++){ //for each band | ||
1015 | + if(b != band_array[i]){ //if this band is not trimmed | ||
1016 | + file.read((char*)temp, XYb); //read the band | ||
1017 | + out.write((char*)temp, XYb); //output the band | ||
1018 | + } | ||
1019 | + else{ | ||
1020 | + file.seekg(XYb, std::ios::cur); //otherwise, skip the band | ||
1021 | + i++; | ||
1022 | + } | ||
1023 | + if(PROGRESS) progress = (double)(b+1) / (double) Z() * 100; | ||
1024 | + } | ||
1025 | + free(temp); //free the scratch space for the band | ||
1026 | + } | ||
1027 | + | ||
999 | 1028 | ||
1000 | /// Close the file. | 1029 | /// Close the file. |
1001 | bool close(){ | 1030 | bool close(){ |
stim/envi/envi.h
@@ -1235,6 +1235,64 @@ public: | @@ -1235,6 +1235,64 @@ public: | ||
1235 | return false; | 1235 | return false; |
1236 | } | 1236 | } |
1237 | 1237 | ||
1238 | + /// Remove a list of bands from the ENVI file | ||
1239 | + | ||
1240 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | ||
1241 | + /// @param b is an array of bands to be eliminated | ||
1242 | + void trim(std::string outfile, std::vector<size_t> trimmed, bool PROGRESS = false){ | ||
1243 | + | ||
1244 | + envi_header h = header; | ||
1245 | + h.bands = header.bands - trimmed.size(); //calculate the new number of bands | ||
1246 | + if(header.wavelength.size() != 0) | ||
1247 | + h.wavelength.resize(h.bands); | ||
1248 | + if(header.band_names.size() != 0) | ||
1249 | + h.band_names.resize(h.bands); | ||
1250 | + size_t it = 0; //allocate an index into the trimmed bands array | ||
1251 | + size_t i = 0; | ||
1252 | + for(size_t b = 0; b < header.bands; b++){ //for each band | ||
1253 | + if(b != trimmed[it]){ | ||
1254 | + if(h.wavelength.size()) h.wavelength[i] = header.wavelength[b]; | ||
1255 | + if(h.band_names.size()) h.band_names[i] = header.band_names[i]; | ||
1256 | + i++; | ||
1257 | + } | ||
1258 | + else it++; | ||
1259 | + } | ||
1260 | + h.save(outfile + ".hdr"); | ||
1261 | + | ||
1262 | + if (header.interleave == envi_header::BSQ){ | ||
1263 | + if (header.data_type == envi_header::float32) | ||
1264 | + return ((bsq<float>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1265 | + else if (header.data_type == envi_header::float64) | ||
1266 | + return ((bsq<double>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1267 | + else{ | ||
1268 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1269 | + exit(1); | ||
1270 | + } | ||
1271 | + } | ||
1272 | + else if (header.interleave == envi_header::BIL){ | ||
1273 | + if (header.data_type == envi_header::float32) | ||
1274 | + return ((bil<float>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1275 | + else if (header.data_type == envi_header::float64) | ||
1276 | + return ((bil<double>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1277 | + else{ | ||
1278 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1279 | + exit(1); | ||
1280 | + } | ||
1281 | + } | ||
1282 | + else if (header.interleave == envi_header::BIP){ | ||
1283 | + if (header.data_type == envi_header::float32) | ||
1284 | + return ((bip<float>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1285 | + else if (header.data_type == envi_header::float64) | ||
1286 | + return ((bip<double>*)file)->trim(outfile, trimmed, PROGRESS); | ||
1287 | + else{ | ||
1288 | + std::cout << "ERROR: unidentified data type" << std::endl; | ||
1289 | + exit(1); | ||
1290 | + } | ||
1291 | + } | ||
1292 | + | ||
1293 | + | ||
1294 | + } | ||
1295 | + | ||
1238 | }; | 1296 | }; |
1239 | 1297 | ||
1240 | } //end namespace rts | 1298 | } //end namespace rts |
stim/envi/envi_header.h
@@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
6 | #include <fstream> | 6 | #include <fstream> |
7 | #include <sstream> | 7 | #include <sstream> |
8 | #include <vector> | 8 | #include <vector> |
9 | +#include <algorithm> | ||
9 | #include <stdlib.h> | 10 | #include <stdlib.h> |
10 | 11 | ||
11 | //information from an ENVI header file | 12 | //information from an ENVI header file |
@@ -431,6 +432,68 @@ struct envi_header | @@ -431,6 +432,68 @@ struct envi_header | ||
431 | std::string interleave_str(){ | 432 | std::string interleave_str(){ |
432 | return interleave_str(interleave); | 433 | return interleave_str(interleave); |
433 | } | 434 | } |
435 | + | ||
436 | + /// Convert a wavelength to a band index (or a pair of surrounding band indices) | ||
437 | + std::vector<size_t> band_index(double w){ | ||
438 | + std::vector<size_t> idx; //create an empty array of indices | ||
439 | + if(w < wavelength[0] || w > wavelength[bands-1]) return idx; //if the wavelength range is outside of the file, return an empty array | ||
440 | + | ||
441 | + for(size_t b = 0; b < bands; b++){ //for each band in the wavelength vector | ||
442 | + if(wavelength[b] == w){ //if an exact match is found | ||
443 | + idx.push_back(b); //add the band to the array and return it | ||
444 | + return idx; | ||
445 | + } | ||
446 | + if(wavelength[b] >= w){ //if the current wavelength exceeds w | ||
447 | + idx.resize(2); | ||
448 | + idx[0] = b-1; //push both the previous and current band index | ||
449 | + idx[1] = b; | ||
450 | + return idx; //return the pair of indices | ||
451 | + } | ||
452 | + } | ||
453 | + return idx; | ||
454 | + } | ||
455 | + | ||
456 | + /// Convert a wavelength range to a list of bands | ||
457 | + std::vector<size_t> band_indices(double w0, double w1){ | ||
458 | + | ||
459 | + size_t idx0 = 0; | ||
460 | + size_t idx1 = 0; //declare the interval indices for the band range | ||
461 | + | ||
462 | + //get the indices for the first wavelength | ||
463 | + std::vector<size_t> r; | ||
464 | + | ||
465 | + if(w0 > wavelength[bands-1] || w1 < wavelength[0]){ | ||
466 | + std::cout<<"ERROR in envi_header::band_indices - wavelengths are completely out of range: ["<<w0<<", "<<w1<<"]"<<std::endl; | ||
467 | + exit(1); | ||
468 | + } | ||
469 | + if(w0 < wavelength[0]) //if the lower wavelength is outside the file range | ||
470 | + idx0 = 0; //just set it to zero | ||
471 | + else{ | ||
472 | + r = band_index(w0); | ||
473 | + if(r.size() == 1) //if there is an exact match, set the first interval index | ||
474 | + idx0 = r[0]; | ||
475 | + else | ||
476 | + idx0 = r[1]; //otherwise save the highest band index (this is the first band with wavelength > w0) | ||
477 | + } | ||
478 | + //get the indices for the second wavelength | ||
479 | + if(w1 > wavelength[bands-1]) | ||
480 | + idx1 = bands-1; | ||
481 | + else{ | ||
482 | + r = band_index(w1); | ||
483 | + if(r.size() == 0) | ||
484 | + idx1 = bands - 1; | ||
485 | + else | ||
486 | + idx1 = r[0]; //take the lowest band index (this is the last band < w1) | ||
487 | + } | ||
488 | + | ||
489 | + size_t n = idx1 - idx0 + 1; //calculate the number of bands in this interval | ||
490 | + r.resize(n); //resize the band index array | ||
491 | + for(size_t b = 0; b < n; b++){ //for each band in the interval | ||
492 | + r[b] = idx0 + b; // insert the band in the array | ||
493 | + } | ||
494 | + | ||
495 | + return r; //return the index array | ||
496 | + } | ||
434 | }; //end EnviHeader | 497 | }; //end EnviHeader |
435 | } | 498 | } |
436 | #endif | 499 | #endif |