Line camera
Posted on Fri 02 May 2014 in fun
I wrote this one a while ago, it's a line camera! Check the video for a better explanation.
Look!!
How does it work?
Well, it just takes the center vertical line of the input video (which can be either a video file, or a video straight from the camera) and appends it as a last vertical line in a new image. Simple but you can get nice outputs. Yay!
Show me the code!
The code was written in c++ and it uses OpenCV.
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main (int argc, char* argv[])
{
if (argc < 3) {
cout << "Something's wrong with the provided parameters..." << endl << endl;
cout << "Usage: ./lineScan streamType streamLocation" << endl << endl;
cout << "streamType - 0 = file, 1 = camera" << endl;
cout << "streamLocation - path to the video stream" << endl;
return 0;
}
int streamType = atoi(argv[1]);
string videoStreamLocation = argv[2];
VideoCapture vcap;
Mat image;
if (streamType == 0) {
if(!vcap.open(videoStreamLocation)) {
cout << "Error opening video stream" << endl;
return 0;
}
}
else {
if(!vcap.open(atoi(argv[2]))) {
cout << "Error opening video stream" << endl;
return 0;
}
vcap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
vcap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
}
namedWindow ("line", CV_WINDOW_AUTOSIZE);
long frame = 0;
Mat lineImage = Mat::zeros(Size(640, 480), CV_8UC3);
Mat combinedImage = Mat::zeros(Size(1280, 480), CV_8UC3);
while(true) {
if(!vcap.read(image)) {
cout << "No frame" << std::endl;
return 0;
}
if (streamType == 0) {
Mat imageScaled(Size(640, 480), image.type());
resize(image, image, imageScaled.size());
}
line(image, Point(image.cols / 2 + 1, 0),
Point(image.cols / 2 + 1, image.rows - 1),
Scalar(255, 0, 128));
if (frame >= lineImage.cols) {
lineImage.colRange(1, lineImage.cols - 1).copyTo(lineImage.colRange(0, lineImage.cols - 2));
image.col(image.cols / 2).copyTo(lineImage.col(lineImage.cols - 2));
}
else {
image.col(image.cols / 2).copyTo(lineImage.col(frame));
}
image.colRange(0, image.cols - 1).copyTo(combinedImage.colRange(0, image.cols - 1));
lineImage.colRange(0, image.cols - 1).copyTo(combinedImage.colRange(image.cols, combinedImage.cols - 1));
imshow("line", combinedImage);
frame ++;
stringstream ss;
ss.fill('0');
ss.width(4);
ss << frame << ".jpg";
/*imwrite(ss.str().c_str(), combinedImage);*/
if(waitKey(1) >= 0) waitKey(0);
}
}
I'll also include the contents of the CMakeLists.txt file, just save this as CMakeLists.txt in the same folder:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
project (LineScan)
find_package (OpenCV REQUIRED)
add_executable(lineScan linescan.cpp)
target_link_libraries (lineScan ${OpenCV_LIBS})
The code is also available on github.
How to compile?
Assuming that you have OpenCV and cmake installed and that you have the linescan.cpp and CMakeLists.txt files in a folder, then you could do something like:
mkdir build cd build cmake .. make
How to run it?
After compiling, just go into the build folder and run the code using:
./lineScan
This will give tell you which parameters the program expects.
How to make your own video?
Uncomment the imwrite line in the source, recompile and run the code. This will save each frame into a .jpg image. To convert the generated sequence of images into a video, you could use something like:
ffmpeg -f image2 -i tmp/%04d.jpg -b 800k video.mpg
That's it! Have fun!