opencv Changing pixel format (YUYV to MJPG) when capturing from webcam? - c++

I need to set my webcam to MJPG using the CV_CAP_PROP_FOURCC property to increase the FPS. If I try to set the parameter to MJPG I get an error of
HIGHGUI ERROR: V4L: Property <unknown property string>(6) not supported by device
cam1x.cpp
#include "opencv2/opencv.hpp"
#include <iostream>
#include <string>
#include <sstream>
#include <stdio.h>
#include <unistd.h>
using namespace cv;
using namespace std;
int main(int, char**)
{
VideoCapture cap(7); // open the default camera
//*********trying to set it here****************
cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M','J','P','G') );
cap.set(CV_CAP_PROP_FRAME_WIDTH,320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT,280);
//cap.set(CV_CAP_PROP_CONTRAST, 0.5);
//cap.set(CV_CAP_PROP_BRIGHTNESS, 0.5);
if(!cap.isOpened() ) // check if we succeeded
return -1;
//double contrast = cap.get(CV_CAP_PROP_CONTRAST);
//double brightness = cap.get(CV_CAP_PROP_BRIGHTNESS);
//cout << "Contrast = " << contrast << "BRIghtness" << brightness << endl;
//Mat edges;
namedWindow("cam1",1);
int x = 0;
while(true)
{
x++;
Mat frame;
if( !cap.grab())
{
cout << "Can not grab images." << endl;
return -1;
}
if(cap.retrieve(frame,3) ){
imshow("cam1", frame);
}
//cap >> frame; // get a new frame from camera
//cap1 >> frame1;
//imshow("edges1", frame1);
//sleep(2);
if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
to show that my camera supports mjpg
v4l2-ctl -d /dev/video7 --list-formats
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'UYVY'
Name : UYVY 4:2:2
Index : 1
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
How do I fix this problem so that I can set the capture to MJPG without error???
Note that there is a similar question to mines on the opencv forum that is UNANSWERED.
http://answers.opencv.org/question/41899/changing-pixel-format-yuyv-to-mjpg-when-capturing-from-webcam/

Related

Saved video doesn't have the same duration as streamed video from a camera

I have a question about saving a video with openCV in C++ (I'm using Linux Ubuntu).
I was trying to save a stream from open camera for some time. I finally succeeded, but now I have really not many ideas why the saved stream doesn't have the same duration as I was streaming from my camera. When I am streaming for 10 seconds it has only for example 2-3 seconds and looks like it is accelerated.
Does anybody have some clue what could be the problem? Something wrong in my code or maybe computing performance, maybe the system doesn't save every frame?
Thanks for your help.
My code:
#include <stdio.h>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp> // Video write
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat capture;
VideoCapture cap(0);
if(!cap.isOpened())
{
cout<<"Cannot connect to camera"<<endl;
return -1;
}
namedWindow("Display",CV_WINDOW_AUTOSIZE);
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
VideoWriter oVideoWriter ("/home/Stream_video/cpp/Cam/out.avi", CV_FOURCC('P','I','M','1'), 20, frameSize,true);
if ( !oVideoWriter.isOpened() ) {
cout << "ERROR: Failed to write the video" << endl;
return -1;
}
while(true){
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) {
cout << "ERROR: Cannot read a frame from video file" << endl;
break; //if not success, break loop
}
oVideoWriter.write(frame); //writer the frame into the file
imshow("Display", frame);
if (waitKey(10) == 27) {
cout << "esc key is pressed by user" << endl;
break;
}
}
}

Grayscale video file corrupted in OpenCV3.3, MJPG codec

My setup is using a logitech c920, raspberry pi 3, and the latest opencv 3.3. I am showing in screen and writing in a file the camera stream. The only processing I am doing is converting video to grayscale. In the screen all show good, but the file is corrupted (see https://i.stack.imgur.com/QHrQb.png).
Noticeable, the video is well recorded in XVID, and also in MJPG if the original color image is selected instead.
UPDATE: I tested the same code in os-x and the same error happens, also with opencv3.3
Any advice welcome :)
This is the code:
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main() {
int FPS = 10;
int nframes;
double start, now;
VideoCapture vcap(0);
if(!vcap.isOpened()) {
cout << "Error opening video stream or file" << endl;
return 0;
}
vcap.set(CV_CAP_PROP_FOURCC,CV_FOURCC('M','J','P','G'));
int frame_width = vcap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
VideoWriter video("out.avi",CV_FOURCC('M','J','P','G'), FPS, Size(frame_width,frame_height), false);
namedWindow("Main",CV_WINDOW_AUTOSIZE); //create a window called
// Start time
start = (double)getTickCount();
for(;;) {
Mat frame, gray;
vcap >> frame;
cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
video << gray;
imshow("Main", gray);
char c = (char)waitKey(2);
if( c == 27 ) break;
++nframes;
if (nframes==100) {
now = (double)getTickCount();
cout << "FPS: " << ++nframes/(now-start)*getTickFrequency() << endl;
start = now;
nframes = 0;
}
}
video.release();
return 0;
}

Background subtraction with shadow removal

I'm working with KTH dataset which contains videos for basic human action. I've tried to subtract the background using opencv-2.4.9 BackgroundSubtractorMOG2, but still getting the shadows in the result.
Here is the code (written in C++) that I'm using:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
//C
#include <stdio.h>
//C++
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
//global variables
Mat frame; //current frame
Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
int keyboard;
//function declarations
void processVideo(char* videoFilename);
int main(int argc, char* argv[])
{
pMOG2 = new BackgroundSubtractorMOG2(); //MOG2 approach
pMOG2->setInt("nmixtures",3);
pMOG2->setDouble("fTau",0.5);
processVideo("person14_boxing_d1_uncomp.avi");// read the avi file
//destroy GUI windows
destroyAllWindows();
return EXIT_SUCCESS;
}
void processVideo(char* videoFilename) {
//create the capture object
VideoCapture capture(videoFilename);
if(!capture.isOpened()){
//error in opening the video input
cerr << "Unable to open video file: " << videoFilename << endl;
exit(EXIT_FAILURE);
}
//read input data. ESC or 'q' for quitting
while( (char)keyboard != 'q' && (char)keyboard != 27 ){
//read the current frame
if(!capture.read(frame)) {
cerr << "Unable to read next frame." << endl;
cerr << "Exiting..." << endl;
//exit(EXIT_FAILURE);
return;
}
pMOG2->operator()(frame, fgMaskMOG2, 0.1
imshow("FG Mask MOG 2", fgMaskMOG2);
//get the input from the keyboard
keyboard = waitKey( 30 );
}
//delete capture object
capture.release();
}
So please help me to change the code so that I can get a better result.

OpenCV: Debug Assertion Fail (pHead->nBlockUse)

My program is getting an input from the webcam and outputting the Gaussian Pyramid in real time. The program runs fine, but when I exit (by pressing a key to trigger the waitKey()), I get an error:
Debug Assertion Failed!
_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))
Line 52: dbgdel.cpp
I suspect this is related to the buildPyramid() function I am using to create the Gaussian Pyramid. The output requires an Array of Mat. The number of mats that are output depends on the number of levels, so the output needs to be a pointer. I don't know if the problem is with initializing the variable or if it doesn't get deleted at the end. I could also just be completely off about the cause.
I am making the Array of Arrays with this:
std::vector<cv::Mat> GPyr;
and I am making the Gaussian Pyramid with this:
buildPyramid(imgMatNew, GPyr, levels, BORDER_DEFAULT);
Any ideas for what is causing the error?
Full Source:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2\objdetect\objdetect.hpp"
using namespace cv;
using namespace std;
int main()
{
CvCapture* capture = 0;
// imgMatNew, imgMatOut were used to grab the current frame
Mat frame, frameCopy, image, imgMatNew, imgMatOut;
std::vector<cv::Mat> GPyr;
int levels = 4;
capture = cvCaptureFromCAM(CV_CAP_ANY); //0=default, -1=any camera, 1..99=your camera
if (!capture)
{
cout << "No camera detected" << endl;
}
//cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
namedWindow("GPyrOut", WINDOW_AUTOSIZE);
namedWindow("imageNew", WINDOW_AUTOSIZE);
if (capture)
{
cout << "In capture ..." << endl;
for (;;)
{
// capture frame from video camera
IplImage* iplImg = cvQueryFrame(capture);
frame = iplImg;
// convert ilpImg into Mat format for easy processing
imgMatNew = cvarrToMat(iplImg, 1);
// Start Image Processing Here
buildPyramid(imgMatNew, GPyr, levels, BORDER_DEFAULT);
// Show Window
imshow("GPyrOut", GPyr[levels]); //show G Pyr, at a certain level, mex index = levels
imshow("imageNew", imgMatNew); //show window
if (waitKey(10) >= 0)
break;
}
// waitKey(0);
}
cvReleaseCapture(&capture);
return 0;
}
so, there's 2 things wrong here.
a) you must not use opencv's outdated c-api, mixing c and c++ calls is the straight road to hell.
b) c++ starts indexing at 0, and the last valid index is size-1, so for 4 levels, levels[4] is out of bounds. please run a debug build to get proper exceptions in this case !
here's the corrected code:
Mat frame, frameCopy, image, imgMatNew, imgMatOut;
std::vector<cv::Mat> GPyr;
int levels = 4;
VideoCapture capture(0);
if (!capture.isOpened())
{
cout << "No camera detected" << endl;
return -1;
}
//cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
namedWindow("GPyrOut", WINDOW_AUTOSIZE);
namedWindow("imageNew", WINDOW_AUTOSIZE);
cout << "In capture ..." << endl;
for (;;)
{
// capture frame from video camera
capture.read(frame);
// Start Image Processing Here
buildPyramid(frame, GPyr, levels, BORDER_DEFAULT);
// Show Window
imshow("GPyrOut", GPyr[levels-1]); //show last level
imshow("imageNew", frame); //show window
if (waitKey(10) >= 0)
break;
}

See a black frame instead of a depth image with ASUS Xtion Pro and OpenCV

I can actually get a RGB image from my ASUS Xtion but cannot get any Depth image. I see a black image instead and no error shows up.
The sample SimpleView given with OpenNI works, so I guess it's not the sensor, not the library and OpenCV seems to work correctly.
Any idea?
Here is my code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char* argv[] )
{
cout << "Device opening ..." << endl;
VideoCapture captureStream;
captureStream.open(CV_CAP_OPENNI_ASUS);
if( !captureStream.isOpened() ){
cout << "Can not open capture object." << endl;
return -1;
}
for(;;){
Mat depth;
if( !captureStream.grab() ){
cout << "ASUS Xtion can not grab images." << endl;
return -1;
}else
if( captureStream.retrieve( depth, CV_CAP_OPENNI_DEPTH_MAP) )
imshow("depth",depth);
if( waitKey( 30 ) == 27 ) break;
}
return 0;
}
Thank you!
The OpenCV sample code actually uses this code to retrieve and display the depth-map:
Mat depth;
capture.retrieve( depth, CV_CAP_OPENNI_DEPTH_MAP )
const float scaleFactor = 0.05f;
Mat show;
depth.convertTo( show, CV_8UC1, scaleFactor );
imshow( "depth map", show );