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
Related
My problem is this:
I need to get the webcam video, get each frame of the video as VP8 frames to packetize it on a RTP stream or to directly get/create an RTP stream to send through a WebRTC application.
I saw that I can get the camera via OpenCV this is an complete example:
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include <iostream>
using namespace cv;
using namespace std;
void drawText(Mat & image);
int main()
{
cout << "Built with OpenCV " << CV_VERSION << endl;
Mat image;
VideoCapture capture;
capture.open(0); // webcam device
if(capture.isOpened())
{
cout << "Capture is opened" << endl;
for(;;)
{
capture >> image;
if(image.empty())
break;
drawText(image);
imshow("Sample", image);
if(waitKey(10) >= 0)
break;
}
}
else
{
cout << "No capture" << endl;
image = Mat::zeros(480, 640, CV_8UC1);
drawText(image);
imshow("Sample", image);
waitKey(0);
}
return 0;
}
void drawText(Mat & image)
{
putText(image, "Hello OpenCV",
Point(20, 50),
FONT_HERSHEY_COMPLEX, 1, // font face and scale
Scalar(255, 255, 255), // white
1, LINE_AA); // line thickness and type
}
I have "Mat image", so I can the the Mat (each video frame into a OpenCV Mat) on the line:
capture >> image;
is it possible to get the bytes from the Mat class and encode it into a VP8 frame?
I saw there is a VideoWriter class on OpenCV where I can setup the VP8 encoding, but id like not to save anything on disk since I only need the VP8 bytes to send over a stream.
Is it possible to get the bytes from the camera and encode it to a VP8 frame or even to get the whole camera recording and setup a RTP stream with OpenCV?
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.
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 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;
}
}
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;
}