00001
00002
00003 #include "FCam/F2.h"
00004 #include <cmath>
00005 #include <algorithm>
00006 #include <fstream>
00007 #include <stdio.h>
00008
00009 typedef std::vector<FCam::Shot> Burst;
00010
00011 void roiTimingTest() {
00012 using namespace FCam::F2;
00013 using namespace std;
00014 char buf[256];
00015 FILE *fp;
00016
00017 printf("roiTimingTest: Tabulating frame time changes with ROI\n"
00018 "-------------------------------------------\n");
00019
00020 fp = fopen("roiTiming.csv", "w");
00021 if (fp == NULL) {
00022 printf("Unable to open stats file roiTiming.csv, exiting\n");
00023 return;
00024 }
00025
00026 int e[] = {1000,5000,10000,20000,40000,80000};
00027 vector<int> exposures(e, e + sizeof(e)/sizeof(int));
00028
00029 int ft[] = {15000,20000,40000,80000};
00030 vector<int> frameTimes(ft, ft + sizeof(ft)/sizeof(int));
00031
00032
00033
00034 RowSkip::e rs[] = { RowSkip::none, RowSkip::x2, RowSkip::x4};
00035
00036 vector<RowSkip::e> rowSkips(rs, rs + 3);
00037
00038
00039
00040 ColSkip::e cs[] = { ColSkip::none, ColSkip::x2, ColSkip::x4};
00041
00042 vector<ColSkip::e> colSkips(cs, cs + 3);
00043
00044
00045 RowBin::e rb[] = { RowBin::none, RowBin::x2, RowBin::x4 };
00046 vector<RowBin::e> rowBins(rb, rb + 3);
00047
00048 ColBin::e cb[] = { ColBin::none, ColBin::x2, ColBin::x4 };
00049 vector<ColBin::e> colBins(cb, cb + 3);
00050
00051 vector<bool> changeRoiXY(2);
00052 changeRoiXY[0] = false;
00053 changeRoiXY[1] = true;
00054
00055 int roiXstd = 0;
00056 int roiYstd = 0;
00057 int roiXchg = 500;
00058 int roiYchg = 500;
00059
00060 int dstRealFT, srcRealFT;
00061 int dstRealExp, srcRealExp;
00062
00063 Shot srcShot, dstShot;
00064 srcShot.gain = 8;
00065 srcShot.image = FCam::Image(640,480,FCam::UYVY, FCam::Image::Discard);
00066 dstShot = srcShot;
00067
00068 Sensor sensor;
00069
00070 unsigned int burstCount = 10;
00071 unsigned int n = 6;
00072
00073 snprintf(buf, 256, "sExp(ms), sFT(ms), sRS, sCS, sRB, sCB, sSX, sSY, dExp(ms), dFT(ms), dRS, dCS, dRB, dCB, dSX, dSY");
00074 printf(buf); fprintf(fp, buf);
00075 for (unsigned int k=0; k <n ; k++) {
00076 snprintf(buf, 256, ", exp_ms[%d], ft_ms[%d], avg_dT_ms[%d], std_dT_us[%d], cnt[%d]", k,k,k,k,k);
00077 printf(buf); fprintf(fp, buf);
00078 }
00079 snprintf(buf, 256, "\n");
00080 printf(buf); fprintf(fp,buf);
00081
00082 for (vector<int>::iterator fTime = frameTimes.begin(); fTime != frameTimes.end(); fTime++) {
00083 for (vector<int>::iterator exp = exposures.begin(); exp != exposures.end(); exp++) {
00084
00085 for (int sb=0; sb < 3; sb++) {
00086 srcShot.roiStartX = roiXstd;
00087 srcShot.roiStartY = roiYstd;
00088 srcShot.rowSkip = rowSkips[sb]; srcShot.colSkip = colSkips[sb];
00089 srcShot.rowBin = rowBins[sb]; srcShot.colBin = colBins[sb];
00090 srcShot.frameTime = *fTime;
00091 srcShot.exposure = *exp;
00092 for (vector<int>::iterator fTime2 = frameTimes.begin(); fTime2 != frameTimes.end(); fTime2++) {
00093 for (vector<int>::iterator exp2 = exposures.begin(); exp2 != exposures.end(); exp2++) {
00094 for (int sb2 =0; sb2< 3; sb2++) {
00095 dstShot.roiStartX = roiXstd;
00096 dstShot.roiStartY = roiYstd;
00097 dstShot.rowSkip = rowSkips[sb2]; dstShot.colSkip = colSkips[sb2];
00098 dstShot.rowBin = rowBins[sb2]; dstShot.colBin = colBins[sb2];
00099 dstShot.frameTime = *fTime2;
00100 dstShot.exposure = *exp2;
00101
00102 std::vector<Shot> testBurst(n);
00103
00104 unsigned int i=0;
00105 for (; i < n/2; i++) {
00106 testBurst[i] = srcShot;
00107 }
00108 for (; i < n; i++) {
00109 testBurst[i] = dstShot;
00110 }
00111 int chgIndex = n/2;
00112
00113 sensor.debugTiming(true);
00114
00115 sensor.capture(dstShot);
00116 for (unsigned int i=0; i< burstCount; i++) sensor.capture(testBurst);
00117
00118 FCam::Time prevT;
00119 {
00120 Frame::Ptr f = sensor.getF2Frame();
00121 prevT = f->processingDoneTime;
00122 }
00123 vector<float> dT[n];
00124 float driverExp[n], driverFT[n];
00125 for (unsigned int i=0;i<n;i++) driverExp[i] = driverFT[i] = 0;
00126
00127 int testFrames = burstCount * n;
00128 int index = 0;
00129 while (testFrames-- > 0) {
00130 Frame::Ptr f = sensor.getF2Frame();
00131
00132 float deltaT = (f->processingDoneTime - prevT) / 1000.0;
00133 prevT = f->processingDoneTime;
00134
00135 dT[index].push_back(deltaT);
00136 driverExp[index] += f->exposure;
00137 driverFT[index] += f->frameTime;
00138 index = (index + 1) % n;
00139 }
00140
00141 float avg[n];
00142 float std[n];
00143 for (unsigned int k=0;k<n;k++) {
00144 avg[k] = 0;
00145 for (unsigned int i=0; i < dT[k].size(); i++)
00146 avg[k] += dT[k][i];
00147 avg[k] /= dT[k].size();
00148
00149 std[k] = 0;
00150 for (unsigned int i=0; i < dT[k].size(); i++)
00151 std[k] += (dT[k][i] - avg[k])*(dT[k][i] - avg[k]);
00152 std[k] = sqrt( std[k] / dT[k].size());
00153 }
00154
00155 snprintf(buf,256, "%.2f, %.2f, %d, %d, %d, %d, %d, %d, ",
00156 srcShot.exposure/1000.f, srcShot.frameTime/1000.f,
00157 srcShot.rowSkip, srcShot.colSkip, srcShot.rowBin, srcShot.colBin,
00158 srcShot.roiStartX, srcShot.roiStartY);
00159 printf(buf); fprintf(fp, buf);
00160
00161 snprintf(buf,256, "%.2f, %.2f, %d, %d, %d, %d, %d, %d",
00162 dstShot.exposure/1000.f, dstShot.frameTime/1000.f,
00163 dstShot.rowSkip, dstShot.colSkip, dstShot.rowBin, dstShot.colBin,
00164 dstShot.roiStartX, dstShot.roiStartY);
00165 printf(buf); fprintf(fp, buf);
00166 for (unsigned int k=0; k < n; k++) {
00167 if ( k % 3 == 0) printf("\n\t");
00168 snprintf(buf,256, ", %.1f, %.1f, %.2f, %.1f, %d",
00169 driverExp[k]/dT[k].size()/1000, driverFT[k]/dT[k].size()/1000,
00170 avg[k], std[k]*1000, dT[k].size());
00171 printf(buf); fprintf(fp, buf);
00172 }
00173 snprintf(buf,256,"\n");
00174 printf(buf); fprintf(fp,buf);
00175
00176 fflush(fp);
00177 if (sensor.framesPending()) {
00178 printf("!! Still got frames, that's not good\n");
00179 }
00180
00181 }
00182 }
00183 }
00184 }
00185 }
00186
00187 }
00188 }
00189
00190 void syncTest() {
00191 using namespace FCam::F2;
00192 using namespace std;
00193
00194 printf("syncTest: Testing basic frame-level control\n"
00195 "-------------------------------------------\n");
00196
00197
00198 Sensor sensor;
00199 unsigned int n = 10;
00200
00201
00202
00203 Burst testShots(1);
00204
00205 testShots[0].exposure = 1000;
00206 testShots[0].gain = 10;
00207 testShots[0].frameTime = 40000;
00208 testShots[0].image = FCam::Image(640, 480, FCam::UYVY);
00209
00210 for (unsigned int i=1; i < n;i++) {
00211 testShots.push_back(testShots[0]);
00212 testShots[i].image = FCam::Image(640,480, FCam::UYVY);
00213 if (i >= n/2) testShots[i].exposure = 20000;
00214 }
00215 testShots[n-1].exposure = 40000;
00216
00217 sensor.stream(testShots);
00218
00219 vector<vector<float> > lums(n);
00220 vector<vector<float> > deltaT(n);
00221
00222 int testFrames = n*10;
00223 FCam::Time prevTime = FCam::Time::now();
00224 bool startup = true;
00225 int startupIgnoreCount = 0;
00226
00227 printf("* Capturing %d frames of a %d-shot burst\n", testFrames, n);
00228 while (testFrames-- > 0) {
00229 unsigned int index;
00230 FCam::Frame::Ptr f = sensor.getFrame();
00231
00232 for (index=0; index<n ;index++ ) {
00233 if (testShots[index].id == f->shot().id) break;
00234 }
00235 if (index == n) {
00236 printf("Unknown frame returned! Something wrong in the shot cloning, perhaps?\n");
00237 exit(0);
00238 }
00239
00240 if (startupIgnoreCount-- == 0)
00241 startup=false;
00242
00243 if (!startup) {
00244 float dt = (f->processingDoneTime-prevTime) / 1000.;
00245 printf("Frame %d: Time from previous frame: %.2f ms, supposed to be %.2f\n", index, dt,
00246 f->frameTime/1000.);
00247 deltaT[index].push_back(dt);
00248 }
00249
00250 prevTime = f->processingDoneTime;
00251
00252 if (!f->image.valid()) {
00253 printf(" Frame %d Came back with no image data!\n", index);
00254 continue;
00255 }
00256
00257
00258 unsigned int totalY=0;
00259 unsigned char *yPtr = f->image.data+1;
00260 unsigned int count=0;
00261 while (yPtr < f->image.data + 2*f->image.size.width*f->image.size.height) {
00262 totalY+= *yPtr;
00263 yPtr += 100;
00264 count++;
00265 }
00266 lums[index].push_back( ((float)totalY)/count);
00267 }
00268 sensor.stopStreaming();
00269
00270 printf("Writing stats to syncTest.csv\n");
00271 ofstream stats("syncTest.csv");
00272 bool done = false;
00273 unsigned int row = 0;
00274 while (!done) {
00275 int haveData=0;
00276 for (unsigned int i=0;i < n; i++) {
00277 if (row < lums[i].size()) {
00278 stats << lums[i][row] << ", ";
00279 haveData++;
00280 } else {
00281 stats << "-1 ,";
00282 }
00283 if (row < deltaT[i].size()) {
00284 stats << deltaT[i][row];
00285 haveData++;
00286 } else {
00287 stats << "-1";
00288 }
00289 if (i < n-1)
00290 stats << " ,";
00291 }
00292 stats << endl;
00293 if (haveData == 0) done = true;
00294 row++;
00295 }
00296 stats.close();
00297
00298 printf("\n\n** Results (Y=sampled luminance per pixel, T=inter-frame time)\n\n");
00299
00300 vector<float> avgsL(n), stddevsL(n), lowboundL(n), highboundL(n);
00301 vector<float> avgsT(n), stddevsT(n), lowboundT(n), highboundT(n);
00302 for (unsigned int i=0;i<n;i++) {
00303 avgsL[i] = 0;
00304 stddevsL[i] = 0;
00305 for (unsigned int j=0;j < lums[i].size(); j++) {
00306 avgsL[i] += lums[i][j];
00307 }
00308 avgsL[i] /= lums[i].size();
00309 for (unsigned int j=0;j < lums[i].size(); j++) {
00310 stddevsL[i] += (lums[i][j] - avgsL[i])*(lums[i][j] - avgsL[i]);
00311 }
00312 stddevsL[i] /= lums[i].size();
00313 stddevsL[i] = sqrt(stddevsL[i]);
00314 sort(lums[i].begin(), lums[i].end());
00315 if (lums[i].size()>10) {
00316 lowboundL[i] = lums[i][lums[i].size()/10];
00317 highboundL[i] = lums[i][lums[i].size()*9/10];
00318 } else {
00319 lowboundL[i]=-1;
00320 highboundL[i]=-1;
00321 }
00322 printf("Shot %d cnt %d, Lum: Avg: %.1f, Std: %.1f, 10%%: %f, 90%%: %f\n", i, lums[i].size(), avgsL[i], stddevsL[i], lowboundL[i], highboundL[i]);
00323 }
00324 printf("\n");
00325 for (unsigned int i=0;i<n;i++) {
00326 avgsT[i] = 0;
00327 stddevsT[i] = 0;
00328 for (unsigned int j=0;j < deltaT[i].size(); j++) {
00329 avgsT[i] += deltaT[i][j];
00330 }
00331 avgsT[i] /= deltaT[i].size();
00332 for (unsigned int j=0;j < deltaT[i].size(); j++) {
00333 stddevsT[i] += (deltaT[i][j] - avgsT[i])*(deltaT[i][j] - avgsT[i]);
00334 }
00335 stddevsT[i] /= deltaT[i].size();
00336 stddevsT[i] = sqrt(stddevsT[i]);
00337 sort(deltaT[i].begin(), deltaT[i].end());
00338 if (deltaT[i].size()>10){
00339 lowboundT[i] = deltaT[i][deltaT[i].size()/10];
00340 highboundT[i] = deltaT[i][deltaT[i].size()*9/10];
00341 } else {
00342 lowboundT[i] = -1;
00343 highboundT[i] = -1;
00344 }
00345 printf("Shot %d, Interframe delay: Avg: %.3f ms, Std: %.2f us, 10%%: %.2f, 90%%: %.2f Exp: %.1f ms\n",
00346 i, avgsT[i], stddevsT[i]*1000, lowboundT[i], highboundT[i], testShots[i].exposure/1000. );
00347 }
00348
00349 printf("syncTest: Done\n"
00350 "-------------------------------------------\n");
00351
00352 }
00353
00354 void basicTest() {
00355 using namespace FCam;
00356 using namespace std;
00357
00358 printf("basicTest: Testing basic capture in all formats\n"
00359 "-------------------------------------------\n");
00360
00361 unsigned int n = 15;
00362 F2::Sensor sensor;
00363 F2::Shot testShot;
00364 AsyncFileWriter writer;
00365
00366 testShot.exposure = 40000;
00367 testShot.frameTime = 0;
00368 testShot.gain = 8;
00369
00370
00371
00372 printf("=== 640x480 UYVY ===\n");
00373 testShot.image = Image(640,480,UYVY, Image::Discard);
00374 testShot.roiRegionSmaller(sensor.maxImageSize());
00375 for (int i=0;i < n;i++) sensor.capture(testShot);
00376 for (int i=0;i < n;i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00377
00378
00379
00380 printf("=== 5MP UYVY ===\n");
00381 testShot.image = Image(sensor.maxImageSize(), UYVY, Image::Discard);
00382 testShot.roiRegionSmaller(sensor.maxImageSize());
00383 {
00384
00385 for (int i=0;i < n;i++) sensor.capture(testShot);
00386 for (int i=0;i < n;i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00387
00388
00389 }
00390
00391
00392
00393 printf("=== 5MP RAW ===\n");
00394 testShot.image = Image(sensor.maxImageSize(), RAW, Image::Discard);
00395 testShot.roiRegionSmaller(sensor.maxImageSize());
00396 {
00397
00398 for (int i=0;i < n;i++) sensor.capture(testShot);
00399 for (int i=0;i < n;i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00400
00401
00402 }
00403
00404
00405 printf("=== 640x480 RAW ===\n");
00406
00407 testShot.image = Image(640,480,RAW, Image::AutoAllocate);
00408 testShot.roiRegionSmaller(sensor.maxImageSize());
00409 for (int i=0;i < n;i++) sensor.capture(testShot);
00410 for (int i=0;i < n;i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00411
00412
00413
00414 printf("=== 640x480 UYVY again ===\n");
00415 testShot.image = Image(640,480,UYVY, Image::Discard);
00416 testShot.roiRegionSmaller(sensor.maxImageSize());
00417 for (int i=0;i < n;i++) sensor.capture(testShot);
00418 for (int i=0;i < n;i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 }
00431
00432 void usage() {
00433 printf("test_F2 Usage:\n\ntest_F2 <test1> <test2> ...\n");
00434 printf("Available tests:\n");
00435 printf("\tb\tBasic\tJust try capturing some frames in UYVY/RAW modes and 640x48/5 MP\n");
00436 printf("\ts\tSync\tTest timing of shot parameter changes\n");
00437 printf("\tr\tRoi Timing\tCollect a lot of statistics. Takes a while, writes roiTiming.csv as it goes\n");
00438 }
00439
00440 int main(int argc, char **argv) {
00441 if (argc > 1) {
00442 printf("Starting F2 FCam API tests\n"
00443 "===============================\n");
00444 for (int i=1; i < argc; i++) {
00445 switch(argv[i][0]) {
00446 case 'b':
00447 case 'B':
00448 basicTest();
00449 break;
00450 case 's':
00451 case 'S':
00452 syncTest();
00453 break;
00454 case 'r':
00455 case 'R':
00456 roiTimingTest();
00457 break;
00458 default:
00459 printf("Unknown test %s\n", argv[0]);
00460 usage();
00461 break;
00462 };
00463 }
00464 printf("===============================\n"
00465 "Done with tests\n"
00466 );
00467
00468 } else {
00469 usage();
00470 }
00471 }