The operations I did were quite simple:
I read an .avi file with a dimension of 1280x720, stored one frame of the video to a Mat object and displayed it.
Here is part of the code:
VideoCapture capL;
capL.open("F:/renderoutput/cube/left.avi");
Mat frameL;
cout << capL.get(CAP_PROP_FRAME_WIDTH) << ", " << capL.get(CAP_PROP_FRAME_HEIGHT) << endl;
for (;;)
{
capL.read(frameL);
cout << frameL.size() << endl;
if (frameL.empty())
break;
imshow("Output", frameL);
waitKey(200);
}
......
But the dimensions of the capL and frameL are not he same, with the former being 1280x720 and latter 1280x360. Why is this happening? I have been using OpenCV 3.3.1 in Visual Studio for quite a long time and some day this happened.
Most likely the video is interlaced. So you have only half height of it in every frame.
Related
I am trying to process recorded videos for feature point recognition. When I process the video at it's full resolution (1280*720) the video playback is slower than it should be. Whenever I reduce the resolution down to 640*360 the fps drops dramatically. What would be the cause of this?
if(captureOpen == false){
img_scene = cvCaptureFromFile("20151115_154042_582.mp4");
}
while(1) {
image = cvQueryFrame(img_scene);
if(image.empty()) {
cout << "IMAGE EMPTY" << endl;
continue;
}
else {
frameCount++;
}
cvtColor(image, gray, CV_BGR2GRAY);
captureOpen = true;
processingThread(gray, imageIndex);
myfile << cvGetCaptureProperty(img_scene, CV_CAP_PROP_POS_FRAMES) << endl;
imshow("Output", gray);
key = cvWaitKey(5);
I've tried reducing cvWaitKey(); to 1 but it doesn't seem to have any noticeable effect on fps, I've also tried removing the gray scale conversion but that does not have a noticeable effect either.
(I've tried both handbrake and ffmpeg to reduce the resolution)
I am trying to write each frame from a camera into a video. Till here it is fine. However, I want my video to include the shape_predictor too at each frame, so when it is reproduced it also appears on the image. So far I have got this... Any ideas? Thank you
cap >> frame;
cv::VideoWriter oVideoWriter;
// . . .
cv_image<bgr_pixel> cimg(frame); //Mat to something dlib can deal with
frontal_face_detector detector = get_frontal_face_detector();
std::vector<rectangle> faces = detector(cimg);
pose_model(cimg, faces[0]);
oVideoWriter.write(dlib::toMat(cimg)); //Turn it into an Opencv Mat
The shape predictor is not the face detector. You have to first call the face detector, then the shape predictor.
See this example program: http://dlib.net/face_landmark_detection_ex.cpp.html
You initialized the face detector properly..then you have to initialize the tracker. Something like this:
shape_predictor sp;
deserialize("shape_predictor_68_face_landmarks.dat") >> sp;
The model can be found here: http://sourceforge.net/projects/dclib/files/dlib/v18.10/shape_predictor_68_face_landmarks.dat.bz2
The rest of the way, you can just follow the example program I linked above. Here's the portion where the tracker is run. You have to pass to the tracker the output (bounding box) return by the detector for it to work. The code below iterates through all the boxes returned by the detector.
// Now tell the face detector to give us a list of bounding boxes
// around all the faces in the image.
std::vector<rectangle> dets = detector(img);
cout << "Number of faces detected: " << dets.size() << endl;
// Now we will go ask the shape_predictor to tell us the pose of
// each face we detected.
std::vector<full_object_detection> shapes;
for (unsigned long j = 0; j < dets.size(); ++j)
{
full_object_detection shape = sp(img, dets[j]);
cout << "number of parts: "<< shape.num_parts() << endl;
cout << "pixel position of first part: " << shape.part(0) << endl;
cout << "pixel position of second part: " << shape.part(1) << endl;
// You get the idea, you can get all the face part locations if
// you want them. Here we just store them in shapes so we can
// put them on the screen.
shapes.push_back(shape);
}
I tried loading a 8 band tiff image into OpenCV C++ but when I checked the dimensions of the image it gives me 3 bands of 1500 by 0 pixels. The image is 1500 by 1500 pixles with 8 bands. Is there a place I am going wrong? My code is as below:
int main(int argc, char** argv)
{
Mat Image, Normalized, ImageCopy;
if (argc != 2){
cout << "Define Image location" << endl;
}
else{
Image = imread(argv[1], CV_LOAD_IMAGE_UNCHANGED|CV_LOAD_IMAGE_ANYDEPTH);
}
cout <<" Number of bands \t: " << Image.channels() << "\t Image size\t"<< Image.size() << endl;
//Checking image validity
if(!Image.data){
cout << "Invalid image" <<endl;
return -1;
}
waitKey(0);
return 0;
}
I think you are out of luck, in TiffDecoder::readHeader() there is this:
m_type = CV_MAKETYPE(CV_8U, photometric > 1 ? 3 : 1);
That is, it is using the PHOTOMETRIC tag to set the number of channels to 1 or 3.
For your code to work, you would need it to set the number of channels based on the SAMPLESPERPIXEL tag, but is doesn't. The whole decoder seems to be peppered with the assumption that an image is either grayscale or RGB. Even an RGBA image has its alpha channel discarded.
You could use libtiff directly, using the OpenCV source in grfmt_tiff.cpp as a guide.
I have a series of images saved on my system according to their time stamps.
For example the images are named as:
20140305180348.jpg
20140305180349.jpg
I have 100 such images, I want to open them using OpenCV one after the other. I have tried using cvCapturefromFile() but using it I am able to open just a single image at a time. I want to stitch/join them so that I can make a video.
I am sorry I cannot post the code as I am not allowed to. How do I proceed?
In OpenCV, to write images to a video, you can use VideoWriter (and do it in a loop to read a sequence of images):
VideoWriter outputVideo; // Open the output
// ... set video properties like FPS
if (!outputVideo.isOpened())
{
cout << "Could not open the output video for write: " << source << endl;
return -1;
}
for(...)
{
// read your frame, e.g. to Mat img
// outputVideo.write(img); //save or
outputVideo << img;
}
cout << "Finished writing" << endl;
Check out here for more info.
In this tutorial is an example how to write a video. Just modify the for-loop in the end.
pseudocode:
open videocontainer
int i=0;
while(i<100){
Mat img = imread("path"+to_string(i)+".jpg");
outputvideo << img;
}
close videocontainer
I have multiple recorded video samples, when I run these through my program it returns the FPS among other things. It is accurate enough for all of my video samples (see table below) but when I run a video sample taken through my smartphone it is returning the FPS at 90000, this happens with every video that captured through my smartphone so it is not just a problem with a single video file.
File Actual FPS OpenCV FPS ffmpeg FPS
action-60fps 60 59 60
action-24fps 24 24 24
phone_panning 29 90000 29
What is causing this problem?
EDIT: Managed to forget to add my code...
VideoCapture capture(argv[1]);
Mat frame;
if(capture.isOpened()) {
int fps = capture.get(CV_CAP_PROP_FPS);
int width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "FPS: " << fps << ", width: " << width << ", height: " << height << endl;
VideoWriter writer("output.mpg",
CV_FOURCC('P','I','M','1'), fps, cvSize(width, height), 0); // 0 means gray, 1 means color
if(writer.isOpened()) {
while(true) {
capture >> frame;
if(!frame.empty()) {
imshow("Video", frame);
}
Mat frame_gray = frame.clone();
cvtColor(frame, frame_gray, CV_RGB2GRAY);
writer << frame_gray;
int key = waitKey(25);
if((char)key == 'q') {
break;
}
}
}
}
I had the same problem with opencv in calculating the FPS and number of frames in a video. (It was returning 90,000 for FPS and 5,758,245 for frame count for a 64-second video!!)
According to this answer:
OpenCV captures only a fraction of the frames from a video file
it's an opencv issue and they are working on it.
Another reason could be a problem with file header, mine was caused by converting video format. I solved it by using original video format mp4, instead of avi.