Skip to content

Instantly share code, notes, and snippets.

@cat-in-136
Last active December 23, 2015 04:09
Show Gist options
  • Save cat-in-136/6578367 to your computer and use it in GitHub Desktop.
Save cat-in-136/6578367 to your computer and use it in GitHub Desktop.
C++/OpenCV implementation of super long exposure ( www.flickr.com/photos/27992339@N00/9655979716/ )
// vim: filetype=cpp fileencoding=UTF-8 shiftwidth=2 tabstop=2 autoindent expandtab
//
// compile
// % g++ -o super_long_exposure super_long_exposure.cpp -fopenmp -O3 -Wall `pkg-config --libs --cflags opencv` -lm
#include <opencv2/opencv.hpp>
#include <iostream>
#include <climits>
#include <cassert>
template <class T> inline T pointer_cast(void *p)
{
return static_cast<T>(p);
}
int main(int argc, char* argv[])
{
assert(CHAR_BIT == 8);
if (argc == 1) {
std::cerr << "Usage: %s moviefile.avi output.png" << std::endl;
return 1;
}
// Load parameter.
if (argc != 3) {
std::cerr << "Error: Specify a movie and output file." << std::endl;
return -1;
}
std::string movFilepath = std::string(argv[1]);
std::string outFilepath = std::string(argv[2]);
std::cout << "Input movie file: " << movFilepath << std::endl;
std::cout << "Output image file: " << outFilepath << std::endl;
// Open the movie file.
cv::VideoCapture capture(movFilepath);
if (capture.isOpened() == false) {
std::cerr << "Error: Could not load " << movFilepath << std::endl;
return -1;
}
capture.set(CV_CAP_PROP_CONVERT_RGB, true);
assert(capture.get(CV_CAP_PROP_FORMAT) == CV_8U);
// Query the first frames to get the image width and height.
unsigned int numOfFrames = 0;
unsigned long *workingArray;
cv::Mat frameMat;
cv::Mat outputMat;
if (capture.read(frameMat) == true) {
assert(frameMat.type() == CV_8UC3);
const unsigned char *const frameMatData = frameMat.data;
const size_t dataLength = frameMat.total();
workingArray = new unsigned long[3*dataLength];
memset(workingArray, 0, sizeof(workingArray));
outputMat = cv::Mat::zeros(frameMat.rows, frameMat.cols, CV_16UC3);
#pragma omp parallel for
for (unsigned int i = 0; i < 3*dataLength; i++) {
workingArray[i] += frameMatData[i];
}
numOfFrames++;
std::cout << "." << std::flush;
}
// Query frames...
while (capture.read(frameMat) == true) {
const unsigned char *const frameMatData = frameMat.data;
const size_t dataLength = frameMat.total();
#pragma omp parallel for
for (unsigned int i = 0; i < 3*dataLength; i++) {
workingArray[i] += frameMatData[i];
}
numOfFrames++;
std::cout << "." << std::flush;
}
// Simple color scaling.
{
unsigned short *const outputMatData = pointer_cast<unsigned short*>(outputMat.data);
const size_t dataLength = outputMat.total();
#pragma omp parallel for
for (unsigned int i = 0; i < 3*dataLength; i++) {
outputMatData[i] = (unsigned short) ((unsigned long long)workingArray[i] * 257 / numOfFrames);
}
delete[] workingArray;
}
// output to file.
if (cv::imwrite(outFilepath, outputMat) == false) {
std::cerr << "Error: Output error." << std::endl;
return -1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment