USB camera encoded data stream - c++

Currently, I am working on a streaming project. I need to grab frames from USB camera and send them over TCP.
To open USB camera video stream I'm using cv::VideoCapture. This allows me to read already decoded frames. According to this question I understood that there is no way to get encoded frame data using cv::VideoCapture and I need to encode each frame again and send it whatever I need using cv::imencode. The problem is that I can encode frames to some specific format listed here, and, in case, I use either .jpg or .png the file size still quite big and on receiving side frame rate very poor.
My question is: Is there any way to get mjpeg or h264 encoded data directly
or maybe you can suggest a better way to encode frames.
OpenCV 3.4.3, camera RICOH THETA V, language C++.
My code:
void Streamer::start()
{
cv::Mat img;
cv::VideoCapture cap(0);
cap.set(CV_CAP_PROP_FOURCC, CV_FOURCC('H', '2', '6', '4'));
if (!cap.isOpened())
throw std::invalid_argument("No device found.");
std::vector<int> format_params;
format_params.push_back(CV_LOAD_IMAGE_COLOR);
format_params.push_back(CV_IMWRITE_PNG_STRATEGY);
for (;;)
{
cap.read(img);
cv::imencode(".png", img, buffer_, format_params);
std::string strbuf(buffer_.begin(), buffer_.end());
server_->sendString(socket, strbuf);
}
cap.release();
}

Related

Streaming an IP camera in OpenCV

I am trying to obtain video from an IP camera Axis 6034E using OpenCV in c++.
I can easily read stream using following simple code:
VideoCapture vid;
vid.open("http://user:password#ipaddres/mjpg/video.mjpg");
Mat frame;
while(true){
vid.read(frame);
imshow("frame", frame)
waitKey(10);
}
But my problem is, the password contain # and unfortunately it is the last charterer of the password. Any idea I will appreciate it.
I tried \# and some other encoding methods and it didn't help.

How to detect motion from already store webm video in c++

I want to detect motion in already existing video, The video is stored in the webm format. I have seen some demo of opencv but those samples is capturing the motion of the live webcam streaming.
Is there any library or api which capture the motion of the webm video file in c++?
please help me.
If you have the code that run with the webcam input you only have to change the input type to accept the video file as input.
Basically, you can accomplish it using the VideoCapture object.
cv::VideoCapture cap("path/for/file.fileextension")
and then, putting this input into a Mat datatype (separating by frame):
Mat frame;
cap >> frame;

c++ opencv get encoded webcam stream

I am currently work on a project that capture video from webcam and send the encoded stream via UDP to do a real time streaming.
#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
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
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;
}
return 0;
}
Some people say that the frame get from cap.read(frame) is already the decoded frame,I have no idea how and when does that happen. And what I want is the encoded frame or stream. What should I do to get it? Should I encoded it back again?
According to the docs, calling VideoCapture::read() is equivalent to calling VideoCapture::grab() then VideoCapture::retrieve().
The docs for the Retrieve function say it does indeed decode the frame.
Why not just use the decoded frame; presumably you'd be decoding it at the far end in any case?
OpenCV API does not give access to the encoded frames.
You will have to use a more low-level library, probably device and platform dependent. If your OS is Linux, Video4Linux2 may be an option, there must be equivalent libraries for Windows/MacOS. You may also have a look at mjpg-streamer, which does something very similar to what you want to achieve (on linux only).
Note that the exact encoding of the image will depend on your webcam, some usb webcam support mjpeg compression (or even h264), but other are only able to send raw data (usually in yuv colorspace).
Another option is to grab the decoded image wit Opencv, and reencode it, for example with imencode. It has the advantages of simplicity and portability, but image reencoding will use more resource.

Logitech quickcam pro 9000 Bayer capture with openCV

I'm trying to capture the raw data of the logitech pro 9000 (eg. the so called Bayer pattern). This can be achieved by using the so called bayer application, that can be found floating over the internet. It should return a 8 bit bayer pattern, but the results are quite obviously not such a pattern.
However; The image that is being streamed seems to be quite off. As can be seen in the image below, I get 2 images of the scene in a 3 channel image (meaning 6 channels in total). Each image is 1/4th of the total capture area, so it would seem that there is some kind of YUV data being streamed.
I was unable to convert this data into anything meaningful using the conversions provided by openCV. Any ideas what kind of data is being sent and (more importantly) how to convert this into RGB?
EDIT
As requested; the codesnippet that is used to generate the image.
system("Bayer.exe 1 8"); //Sets the camera to raw mode
// set up camera
VideoCapture capture(0);
if(!capture.isOpened()){
waitKey();
exit(0);
}
Mat capturedFrame;
while(true){
capture>>capturedFrame;
imshow("Raw",capturedFrame);
waitKey(25);
}
How did you get frames from stream using openCV? Can you share some code snippets? There are too many video formats in openCV for getting correct color channel and compressed data.
I think you should be able to obtain correct image frames as mentioned here :
http://forum.openrobotino.org/archive/index.php/t-295.html?s=c33acb1fb91f5916080f8dfd687598ec
This is most likely to happen if the out put data format ( width, height, bit depth, no of channels...) of camera and the data format your program expect is different.
However i could capture of logitec pro cam, simply by using
Mat img;
VideoCapture cap(0);
cap >> img;

converting a UYVY FFmpeg

I want to read and show a video using opencv. I've recorded with Direct-show, the Video has UYVY (4:2:2) codec, since opencv can't read that format, I want to convert the codec to an RGB color model, I readed about ffmpeg and I want to know if it's possible to get this done with it ? if not if you a suggestion I'll be thankful.
As I explained to you before, OpenCV can read some formats of YUV, including UYVY (thanks to FFmpeg/GStreamer). So I believe the cv::Mat you get from the camera is already converted to the BGR color space which is what OpenCV uses by default.
I modified my previous program to store the first frame of the video as PNG:
cv::Mat frame;
if (!cap.read(frame))
{
return -1;
}
cv::imwrite("mat.png", frame);
for(;;)
{
// ...
And the image is perfect. Executing the command file on mat.png reveals:
mat.png: PNG image data, 1920 x 1080, 8-bit/color RGB, non-interlaced
A more accurate test would be to dump the entire frame.data() to the disk and open it with an image editor. If you do that keep in mind that the R and B channels will be switched.