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 }
00148 avg[k] /= dT[k].size();
00149
00150 std[k] = 0;
00151 for (unsigned int i=0; i < dT[k].size(); i++) {
00152 std[k] += (dT[k][i] - avg[k])*(dT[k][i] - avg[k]);
00153 }
00154 std[k] = sqrt(std[k] / dT[k].size());
00155 }
00156
00157 snprintf(buf,256, "%.2f, %.2f, %d, %d, %d, %d, %d, %d, ",
00158 srcShot.exposure/1000.f, srcShot.frameTime/1000.f,
00159 srcShot.rowSkip, srcShot.colSkip, srcShot.rowBin, srcShot.colBin,
00160 srcShot.roiStartX, srcShot.roiStartY);
00161 printf(buf); fprintf(fp, buf);
00162
00163 snprintf(buf,256, "%.2f, %.2f, %d, %d, %d, %d, %d, %d",
00164 dstShot.exposure/1000.f, dstShot.frameTime/1000.f,
00165 dstShot.rowSkip, dstShot.colSkip, dstShot.rowBin, dstShot.colBin,
00166 dstShot.roiStartX, dstShot.roiStartY);
00167 printf(buf); fprintf(fp, buf);
00168 for (unsigned int k=0; k < n; k++) {
00169 if (k % 3 == 0) { printf("\n\t"); }
00170 snprintf(buf,256, ", %.1f, %.1f, %.2f, %.1f, %d",
00171 driverExp[k]/dT[k].size()/1000, driverFT[k]/dT[k].size()/1000,
00172 avg[k], std[k]*1000, dT[k].size());
00173 printf(buf); fprintf(fp, buf);
00174 }
00175 snprintf(buf,256,"\n");
00176 printf(buf); fprintf(fp,buf);
00177
00178 fflush(fp);
00179 if (sensor.framesPending()) {
00180 printf("!! Still got frames, that's not good\n");
00181 }
00182
00183 }
00184 }
00185 }
00186 }
00187 }
00188
00189 }
00190 }
00191
00192 void syncTest() {
00193 using namespace FCam::F2;
00194 using namespace std;
00195
00196 printf("syncTest: Testing basic frame-level control\n"
00197 "-------------------------------------------\n");
00198
00199
00200 Sensor sensor;
00201 unsigned int n = 10;
00202
00203
00204
00205 Burst testShots(1);
00206
00207 testShots[0].exposure = 1000;
00208 testShots[0].gain = 10;
00209 testShots[0].frameTime = 40000;
00210 testShots[0].image = FCam::Image(640, 480, FCam::UYVY);
00211
00212 for (unsigned int i=1; i < n; i++) {
00213 testShots.push_back(testShots[0]);
00214 testShots[i].image = FCam::Image(640,480, FCam::UYVY);
00215 if (i >= n/2) { testShots[i].exposure = 20000; }
00216 }
00217 testShots[n-1].exposure = 40000;
00218
00219 sensor.stream(testShots);
00220
00221 vector<vector<float> > lums(n);
00222 vector<vector<float> > deltaT(n);
00223
00224 int testFrames = n*10;
00225 FCam::Time prevTime = FCam::Time::now();
00226 bool startup = true;
00227 int startupIgnoreCount = 0;
00228
00229 printf("* Capturing %d frames of a %d-shot burst\n", testFrames, n);
00230 while (testFrames-- > 0) {
00231 unsigned int index;
00232 FCam::Frame::Ptr f = sensor.getFrame();
00233
00234 for (index=0; index<n ; index++) {
00235 if (testShots[index].id == f->shot().id) { break; }
00236 }
00237 if (index == n) {
00238 printf("Unknown frame returned! Something wrong in the shot cloning, perhaps?\n");
00239 exit(0);
00240 }
00241
00242 if (startupIgnoreCount-- == 0) {
00243 startup=false;
00244 }
00245
00246 if (!startup) {
00247 float dt = (f->processingDoneTime-prevTime) / 1000.;
00248 printf("Frame %d: Time from previous frame: %.2f ms, supposed to be %.2f\n", index, dt,
00249 f->frameTime/1000.);
00250 deltaT[index].push_back(dt);
00251 }
00252
00253 prevTime = f->processingDoneTime;
00254
00255 if (!f->image.valid()) {
00256 printf(" Frame %d Came back with no image data!\n", index);
00257 continue;
00258 }
00259
00260
00261 unsigned int totalY=0;
00262 unsigned char *yPtr = f->image.data+1;
00263 unsigned int count=0;
00264 while (yPtr < f->image.data + 2*f->image.size.width*f->image.size.height) {
00265 totalY+= *yPtr;
00266 yPtr += 100;
00267 count++;
00268 }
00269 lums[index].push_back(((float)totalY)/count);
00270 }
00271 sensor.stopStreaming();
00272
00273 printf("Writing stats to syncTest.csv\n");
00274 ofstream stats("syncTest.csv");
00275 bool done = false;
00276 unsigned int row = 0;
00277 while (!done) {
00278 int haveData=0;
00279 for (unsigned int i=0; i < n; i++) {
00280 if (row < lums[i].size()) {
00281 stats << lums[i][row] << ", ";
00282 haveData++;
00283 } else {
00284 stats << "-1 ,";
00285 }
00286 if (row < deltaT[i].size()) {
00287 stats << deltaT[i][row];
00288 haveData++;
00289 } else {
00290 stats << "-1";
00291 }
00292 if (i < n-1) {
00293 stats << " ,";
00294 }
00295 }
00296 stats << endl;
00297 if (haveData == 0) { done = true; }
00298 row++;
00299 }
00300 stats.close();
00301
00302 printf("\n\n** Results (Y=sampled luminance per pixel, T=inter-frame time)\n\n");
00303
00304 vector<float> avgsL(n), stddevsL(n), lowboundL(n), highboundL(n);
00305 vector<float> avgsT(n), stddevsT(n), lowboundT(n), highboundT(n);
00306 for (unsigned int i=0; i<n; i++) {
00307 avgsL[i] = 0;
00308 stddevsL[i] = 0;
00309 for (unsigned int j=0; j < lums[i].size(); j++) {
00310 avgsL[i] += lums[i][j];
00311 }
00312 avgsL[i] /= lums[i].size();
00313 for (unsigned int j=0; j < lums[i].size(); j++) {
00314 stddevsL[i] += (lums[i][j] - avgsL[i])*(lums[i][j] - avgsL[i]);
00315 }
00316 stddevsL[i] /= lums[i].size();
00317 stddevsL[i] = sqrt(stddevsL[i]);
00318 sort(lums[i].begin(), lums[i].end());
00319 if (lums[i].size()>10) {
00320 lowboundL[i] = lums[i][lums[i].size()/10];
00321 highboundL[i] = lums[i][lums[i].size()*9/10];
00322 } else {
00323 lowboundL[i]=-1;
00324 highboundL[i]=-1;
00325 }
00326 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]);
00327 }
00328 printf("\n");
00329 for (unsigned int i=0; i<n; i++) {
00330 avgsT[i] = 0;
00331 stddevsT[i] = 0;
00332 for (unsigned int j=0; j < deltaT[i].size(); j++) {
00333 avgsT[i] += deltaT[i][j];
00334 }
00335 avgsT[i] /= deltaT[i].size();
00336 for (unsigned int j=0; j < deltaT[i].size(); j++) {
00337 stddevsT[i] += (deltaT[i][j] - avgsT[i])*(deltaT[i][j] - avgsT[i]);
00338 }
00339 stddevsT[i] /= deltaT[i].size();
00340 stddevsT[i] = sqrt(stddevsT[i]);
00341 sort(deltaT[i].begin(), deltaT[i].end());
00342 if (deltaT[i].size()>10) {
00343 lowboundT[i] = deltaT[i][deltaT[i].size()/10];
00344 highboundT[i] = deltaT[i][deltaT[i].size()*9/10];
00345 } else {
00346 lowboundT[i] = -1;
00347 highboundT[i] = -1;
00348 }
00349 printf("Shot %d, Interframe delay: Avg: %.3f ms, Std: %.2f us, 10%%: %.2f, 90%%: %.2f Exp: %.1f ms\n",
00350 i, avgsT[i], stddevsT[i]*1000, lowboundT[i], highboundT[i], testShots[i].exposure/1000.);
00351 }
00352
00353 printf("syncTest: Done\n"
00354 "-------------------------------------------\n");
00355
00356 }
00357
00358 void basicTest() {
00359 using namespace FCam;
00360 using namespace std;
00361
00362 printf("basicTest: Testing basic capture in all formats\n"
00363 "-------------------------------------------\n");
00364
00365 unsigned int n = 15;
00366 F2::Sensor sensor;
00367 F2::Shot testShot;
00368 AsyncFileWriter writer;
00369
00370 testShot.exposure = 40000;
00371 testShot.frameTime = 0;
00372 testShot.gain = 8;
00373
00374
00375
00376 printf("=== 640x480 UYVY ===\n");
00377 testShot.image = Image(640,480,UYVY, Image::Discard);
00378 testShot.roiRegionSmaller(sensor.maxImageSize());
00379 for (int i=0; i < n; i++) { sensor.capture(testShot); }
00380 for (int i=0; i < n; i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00381
00382
00383
00384 printf("=== 5MP UYVY ===\n");
00385 testShot.image = Image(sensor.maxImageSize(), UYVY, Image::Discard);
00386 testShot.roiRegionSmaller(sensor.maxImageSize());
00387 {
00388
00389 for (int i=0; i < n; i++) { sensor.capture(testShot); }
00390 for (int i=0; i < n; i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00391
00392
00393 }
00394
00395
00396
00397 printf("=== 5MP RAW ===\n");
00398 testShot.image = Image(sensor.maxImageSize(), RAW, Image::Discard);
00399 testShot.roiRegionSmaller(sensor.maxImageSize());
00400 {
00401
00402 for (int i=0; i < n; i++) { sensor.capture(testShot); }
00403 for (int i=0; i < n; i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00404
00405
00406 }
00407
00408
00409 printf("=== 640x480 RAW ===\n");
00410
00411 testShot.image = Image(640,480,RAW, Image::AutoAllocate);
00412 testShot.roiRegionSmaller(sensor.maxImageSize());
00413 for (int i=0; i < n; i++) { sensor.capture(testShot); }
00414 for (int i=0; i < n; i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00415
00416
00417
00418 printf("=== 640x480 UYVY again ===\n");
00419 testShot.image = Image(640,480,UYVY, Image::Discard);
00420 testShot.roiRegionSmaller(sensor.maxImageSize());
00421 for (int i=0; i < n; i++) { sensor.capture(testShot); }
00422 for (int i=0; i < n; i++) { sensor.getFrame(); printf("\tGot frame %d\n", i); }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 }
00435
00436 void usage() {
00437 printf("test_F2 Usage:\n\ntest_F2 <test1> <test2> ...\n");
00438 printf("Available tests:\n");
00439 printf("\tb\tBasic\tJust try capturing some frames in UYVY/RAW modes and 640x48/5 MP\n");
00440 printf("\ts\tSync\tTest timing of shot parameter changes\n");
00441 printf("\tr\tRoi Timing\tCollect a lot of statistics. Takes a while, writes roiTiming.csv as it goes\n");
00442 }
00443
00444 int main(int argc, char **argv) {
00445 if (argc > 1) {
00446 printf("Starting F2 FCam API tests\n"
00447 "===============================\n");
00448 for (int i=1; i < argc; i++) {
00449 switch (argv[i][0]) {
00450 case 'b':
00451 case 'B':
00452 basicTest();
00453 break;
00454 case 's':
00455 case 'S':
00456 syncTest();
00457 break;
00458 case 'r':
00459 case 'R':
00460 roiTimingTest();
00461 break;
00462 default:
00463 printf("Unknown test %s\n", argv[0]);
00464 usage();
00465 break;
00466 };
00467 }
00468 printf("===============================\n"
00469 "Done with tests\n"
00470 );
00471
00472 } else {
00473 usage();
00474 }
00475 }