Last active
December 23, 2015 04:09
-
-
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/ )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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