int main(int argc, char *argv[]) { opterr = 0; int width = -1; int height = -1; int max_frames = -1; const char *in = NULL; const char *out = NULL; bool time = false; int stripType = Blend::STRIP_TYPE_THIN; const struct option long_options[] = { {"width", required_argument, 0, 'w'}, {"height", required_argument, 0, 'h'}, {"in", required_argument, 0, 'i'}, {"out", required_argument, 0, 'o'}, {"strip", required_argument, 0, 's'}, {"max", required_argument, 0, 'm'}, {"time", no_argument , 0, 't'}, {0, 0, 0, 0} }; int c; if (argc == 1) { usage(); return 0; } while (1) { c = getopt_long(argc, argv, "w:h:i:o:s:m:t", long_options, NULL); if (c == -1) { break; } switch (c) { case 'w': width = atoi(optarg); break; case 'h': height = atoi(optarg); break; case 'i': in = optarg; break; case 'o': out = optarg; break; case 't': time = true; break; case 's': stripType = atoi(optarg); break; case 'm': max_frames = atoi(optarg); break; case '?': usage(); return 0; } } // validate if (width <= 0) { std::cerr << "invalid width " << width << std::endl; return 1; } if (height <= 0) { std::cerr << "invalid height " << height << std::endl; return 1; } if (!in) { std::cerr << "input file not provided" << std::endl; return 1; } if (!out) { std::cerr << "output file not provided" << std::endl; return 1; } if (stripType < 0 || stripType > 1) { std::cerr << "invalid strip type " << stripType << std::endl; return 1; } // input int fd = open(in, O_RDONLY); if (fd == -1) { perror("open"); return 1; } int size = (width * height * 12) / 8; std::cout << "input width = " << width << ", height = " << height << std::endl; std::cout << "strip type: " << stripType << " (" << strips[stripType] << ")" << std::endl; int frames = count_frames(fd, size); if (frames == -1) { close(fd); return 1; } if (max_frames > 0) { frames = MIN(frames, max_frames); } // initialize our mosaicer Mosaic m; if (!m.initialize(blendingType, stripType, width, height, frames, true, 5.0f)) { std::cerr << "Failed to initialize mosaicer" << std::endl; close(fd); return 1; } std::vector<int> times; std::vector<unsigned char *> mosaic_frames; unsigned char *in_data = NULL; for (int x = 0; x < frames; x++) { // allocate: if (!in_data) { in_data = new unsigned char[size]; } if (read(fd, in_data, size) == size) { // process int time = timeNow(); int ret = m.addFrame(in_data); time = timeNow() - time; times.push_back(time); if (ret == Mosaic::MOSAIC_RET_OK || ret == Mosaic::MOSAIC_RET_FEW_INLIERS) { mosaic_frames.push_back(in_data); in_data = NULL; } } else { break; } } if (in_data) { delete[] in_data; } close(fd); std::cout << "Used " << mosaic_frames.size() << " frames" << std::endl; // output // TODO: what are those? float progress = 0; bool cancel = false; int64_t stitchingTime = timeNow(); if (m.createMosaic(progress, cancel) != Mosaic::MOSAIC_RET_OK) { std::cerr << "Failed to stitch" << std::endl; return 1; } stitchingTime = timeNow() - stitchingTime; ImageType yuv = m.getMosaic(width, height); ImageType rgb = ImageUtils::allocateImage(width, height, 3); ImageUtils::yvu2rgb(rgb, yuv, width, height); for (int x = 0; x < mosaic_frames.size(); x++) { delete[] mosaic_frames[x]; } mosaic_frames.clear(); bool res = write_png(out, rgb, width, height); ImageUtils::freeImage(rgb); if (!res) { return 1; } std::cout << "Wrote mosaic image to " << out << std::endl; std::cout << "Width = " << width << " height = " << height << std::endl; if (time) { std::cout << "Average frame time = " << std::accumulate(times.begin(), times.end(), 0) / times.size() << "ms" << std::endl; std::cout << "Final stitching time = " << stitchingTime << "ms" << std::endl; } return 0; }
int main(int argc, char **argv) { struct timespec t1, t2, t3; int width, height; float totalElapsedTime = 0; const char *basename; const char *filename; if (argc != 3) { printf("Usage: %s input_dir output_filename\n", argv[0]); return 0; } else { basename = argv[1]; filename = argv[2]; } // Load the images outside the computational kernel int totalFrames = loadImages(basename, width, height); if (totalFrames == 0) { printf("Image files not found. Make sure %s exists.\n", basename); return 1; } printf("%d frames loaded\n", totalFrames); // Interesting stuff is here for (int iteration = 0; iteration < KERNEL_ITERATIONS; iteration++) { Mosaic mosaic; mosaic.initialize(blendingType, stripType, width, height, -1, false, 0); clock_gettime(CLOCK_MONOTONIC, &t1); for (int i = 0; i < totalFrames; i++) { mosaic.addFrame(yvuFrames[i]); } clock_gettime(CLOCK_MONOTONIC, &t2); float progress = 0.0; bool cancelComputation = false; mosaic.createMosaic(progress, cancelComputation); int mosaicWidth, mosaicHeight; ImageType resultYVU = mosaic.getMosaic(mosaicWidth, mosaicHeight); ImageType imageRGB = ImageUtils::allocateImage( mosaicWidth, mosaicHeight, ImageUtils::IMAGE_TYPE_NUM_CHANNELS); clock_gettime(CLOCK_MONOTONIC, &t3); float elapsedTime = (t3.tv_sec - t1.tv_sec) + (t3.tv_nsec - t1.tv_nsec)/1e9; float addImageTime = (t2.tv_sec - t1.tv_sec) + (t2.tv_nsec - t1.tv_nsec)/1e9; float stitchImageTime = (t3.tv_sec - t2.tv_sec) + (t3.tv_nsec - t2.tv_nsec)/1e9; totalElapsedTime += elapsedTime; printf("Iteration %d: %dx%d moasic created: " "%.2f seconds (%.2f + %.2f)\n", iteration, mosaicWidth, mosaicHeight, elapsedTime, addImageTime, stitchImageTime); // Write the output only once for correctness check if (iteration == 0) { ImageUtils::yvu2rgb(imageRGB, resultYVU, mosaicWidth, mosaicHeight); ImageUtils::writeBinaryPPM(imageRGB, filename, mosaicWidth, mosaicHeight); } } printf("Total elapsed time: %.2f seconds\n", totalElapsedTime); return 0; }