I am using OpenCV 2.4.6, VS2010 with Windows 7 64 bit. I could not grab frame from the camera. The code below is working fine for avi file, but not working to capture from camera. Can anyone help me, how can I capture the frame? Thanks in advance.......
Actually problem in this portion:
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video file" << endl;
break;
}
The full source code:
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap(0); // open the video camera no. 0
if(!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
return -1;
}
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Frame size : " << dWidth << " x " << dHeight << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
while(1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video file" << endl;
break;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
You should read the first frame before using while loop like this:
Mat frame;
cap.read(frame);
while(1)
{
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video file" << endl;
break;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
Related
I am trying to do Frame subtraction in a video.Steps I am following
Get a image , convert it into grayscale.
Subtract it from previous frame grayscale.
All I see in diff2(and diff also) a complete black image.One observation I made is that pixel value of gray1 and gray2 become equal.
My code
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <opencv2/video/background_segm.hpp>
#include <iostream>
using namespace cv;
using namespace std;
RNG rng(12345);
int main( int argc, const char** argv )
{
VideoCapture cap(0);
if ( !cap.isOpened() )
{
cout << "Cannot open the web cam" << endl;
return -1;
}
Mat img1,img2,diff,gray1,gray2,diff2;
bool bSuccess = cap.read(img1); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
return -1;
}
cvtColor( img1,gray1, CV_BGR2GRAY );
while (true)
{
bSuccess = cap.read(img2); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
cvtColor( img2,gray2, CV_BGR2GRAY );
absdiff(gray2,gray1,diff);
threshold(diff, diff2, 150, 255, CV_THRESH_BINARY);
cout<<gray2.at<uchar>(100,200) <<endl;
cout<<gray1.at<uchar>(100,200) <<endl;
gray1=gray2;
imshow("1",gray1);
imshow("2",diff2);
if (waitKey(1000) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return -1;
}
please try this code. It looks like you're overwriting gray1 so that gray1 and gray2 use the very same data memory positions.
You could either use gray1=gray2.clone(); instead or use some real "swapping" of the buffers instead of overwriting. My code should perform a simple buffer swapping and has some comments about the problem.
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <opencv2/video/background_segm.hpp>
#include <iostream>
using namespace cv;
using namespace std;
RNG rng(12345);
int main( int argc, const char** argv )
{
VideoCapture cap(0);
if ( !cap.isOpened() )
{
cout << "Cannot open the web cam" << endl;
return -1;
}
Mat img1,img2,diff,gray1,gray2,diff2;
Mat tmp; // used to swap the buffers
bool bSuccess = cap.read(img1); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
return -1;
}
// this will allocate memory of gray1 if not allocated yet
cvtColor( img1,gray1, CV_BGR2GRAY );
while (true)
{
bSuccess = cap.read(img2); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
// memory for gray2 won't be allocated if it is present already => if gray2 and gray1 use the same data memory, you'll overwrite gray1's pixels here and obviously gray1 and gray2 will have the same pixel values then
cvtColor( img2,gray2, CV_BGR2GRAY );
absdiff(gray2,gray1,diff);
threshold(diff, diff2, 150, 255, CV_THRESH_BINARY);
cout<<gray2.at<uchar>(100,200) <<endl;
cout<<gray1.at<uchar>(100,200) <<endl;
// don't lose the memory of gray1
tmp = gray1;
// this means gray1 and gray2 will use the same data memory location
gray1=gray2;
// give gray2 a new data memory location. Since previous gray1 memory is still present but wont be used anymore, use it here.
gray2=tmp;
imshow("1",gray1);
imshow("2",diff2);
if (waitKey(1000) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return -1;
}
in addition, a thres difference threshold of 150 might be very high for common tasks, but it might be ok for your special task. Typical difference values/thresholds in background subtraction for foreground extraction are around 20 to 30 from my experience, but at the end it depends on your task/problem/domain.
Does anyone know a link where I can catch RTSP stream to test video capture with rtsp video source? I have tried it with usb cam and with webcam, but I want to test it with RTSP stream.
Here is the source:
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap("rtsp:\\ANYTHING,PLEASE"); // open the video file for reading
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
return -1;
}
//cap.set(CV_CAP_PROP_POS_MSEC, 300); //start the video at 300ms
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
while(1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
You can simply generate a RTSP stream with Videolan VLC.
Media / Stream / Add any video file / Stream / RTSP Add / Port and path / Video H.264 + MP3 (MP4) / Stream.
Then you obtain a video streaming with something like rtsp://127.0.0.1:8554/vid. Of course you can read that stream using VLC or OpenCV.
dAAvid
I tried to decode QR codes from images like this:
Based on the following code,
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <zbar.h>
#include <iostream>
using namespace cv;
using namespace std;
using namespace zbar;
//g++ main.cpp /usr/local/include/ /usr/local/lib/ -lopencv_highgui.2.4.8 -lopencv_core.2.4.8
int main(int argc, char* argv[])
{
VideoCapture cap(0); // open the video camera no. 0
// cap.set(CV_CAP_PROP_FRAME_WIDTH,800);
// cap.set(CV_CAP_PROP_FRAME_HEIGHT,640);
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the video cam" << endl;
return -1;
}
ImageScanner scanner;
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Frame size : " << dWidth << " x " << dHeight << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
while (1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
Mat grey;
cvtColor(frame,grey,CV_BGR2GRAY);
int width = frame.cols;
int height = frame.rows;
uchar *raw = (uchar *)grey.data;
// wrap image data
Image image(width, height, "Y800", raw, width * height);
// scan the image for barcodes
int n = scanner.scan(image);
// extract results
for(Image::SymbolIterator symbol = image.symbol_begin();
symbol != image.symbol_end();
++symbol) {
vector<Point> vp;
// do something useful with results
cout << "decoded " << symbol->get_type_name() << " symbol \"" << symbol->get_data() << '"' <<" "<< endl;
int n = symbol->get_location_size();
for(int i=0;i<n;i++){
vp.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i)));
}
RotatedRect r = minAreaRect(vp);
Point2f pts[4];
r.points(pts);
for(int i=0;i<4;i++){
line(frame,pts[i],pts[(i+1)%4],Scalar(255,0,0),3);
}
//cout<<"Angle: "<<r.angle<<endl;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
The naive ZLib approach fails 100%. But the zxing barcode scanner app can decode it from the computer screen, so it's definitely contains all the necessary information.
Any idea how to make the scanning more robust?
I am using vs 2010 with opencv version of 2.4.9.while running the program as shown below it reads about 55 frames from the video and then it suddenly stops by giving message that
"cannot read frame" because the cap.read(frame) function return zero
does any body know how to solve it.
the program is
int main(int, char**)
{
VideoCapture cap("C:\\test.avi");
if( ! cap.isOpened () ) // check if we succeeded
return -1;
double frnb ( cap.get ( CV_CAP_PROP_FRAME_COUNT ) );
std::cout << "frame count = " << frnb << endl;
double frmrate ( cap.get ( CV_CAP_PROP_FPS ) );
std::cout << "frame rate = " << frmrate << endl;
double fIdx=1;
String str="Frame";
for(;;) {
Mat frame;
if ( fIdx < 0 || fIdx >= frnb ) break;
std::cout <<fIdx<<endl;//" ";
cap.set ( CV_CAP_PROP_POS_FRAMES , fIdx );
fIdx=fIdx+frmrate*3;
bool success = cap.read(frame);
if ( ! success ) {
cout << "Cannot read frame " << endl;
break;
}
}
return 0;
}
Please replace your for loop with following. I have simplified it.
Please note
1) Don't use calculate idx etc, set and read unless you need to read random frame. For linear frame read, operator >> is good enough.
2) Don't rely on the frame count that you get from CV_CAP_PROP_FRAME_COUNT, if the video or its indexing have some problem, then it is likely cause problem. It is better to check if a frame is empty every-time.
cv::Mat frame;
for (;;)
{
video >> frame;
if (frame.empty())
{
break;
}
//do whatever with frame OR uncomment following line to display frame as video
//cv::imshow("Win_Name", frame); cv::waitKey(25);
}
Let me know in case of any problem or for further help. Happy Coding :)
I am having trouble if understanding certain coding i am sorry if this comes off as stupid but i have a code to capture a video from my webcam i want to get the RGB valuee from the frame, if this is impossible would have to to save a frame as a picture and then get values from it?
const char window_name[]="Webcam";
int main(int argc, char* argv[])
{
/* attempt to capture from any connected device */
CvCapture *capture=cvCaptureFromCAM(CV_CAP_ANY);
if(!capture)
{
printf("Failed to initialise webcam\n");
return -1;
}
/* create the output window */
cvNamedWindow(window_name, CV_WINDOW_NORMAL);
do
{
/* attempt to grab a frame */
IplImage *frame=cvQueryFrame(capture);
if(!frame)
{
printf("Failed to get frame\n");
break;
}
COLORREF myColAbsolute = GetPixel(frame, 10,10);//error in saying frame is not compatible with HDC.
cout << "Red - " << (int)GetRValue(myColAbsolute) << endl;
cout << "Green - " << (int)GetGValue(myColAbsolute) << endl;
cout << "Blue - " << (int)GetBValue(myColAbsolute) << endl;
/* show the frame */
cvShowImage(window_name, frame);
ha ! ( obviously caught with a copy & paste bummer )
GetPixel() is a windows function, not an opencv one. same for GetRValue() and sisters.
you'd use them in the native win32 api, to get a pixel from an HDC, but it won't work with opencv/highgui, since neither HDC, nor HWND are exposed.
since you're obviously a beginner(nothing wrong with that, again!) let me try to talk you out of using the old, 1.0 opencv api(IplImages, cv*Functions) as well,
you should be using the new one(cv::Mat, namespace cv::Functions) instead.
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main()
{
Mat frame;
namedWindow("video", 1);
VideoCapture cap(0);
while ( cap.isOpened() )
{
cap >> frame;
if(frame.empty()) break;
int x=3, y=5;
// Ladies and Gentlemen, the PIXEL!
Vec3b pixel = frame.at<Vec3b>(y,x); // row,col, not x,y!
cerr << "b:" << int(pixel[0]) << " g:" << int(pixel[1]) << " r:" << int(pixel[2]) << endl;
imshow("video", frame);
if(waitKey(30) >= 0) break;
}
return 0;
}