OpenCV cannot connect to video stream - lack of some codec? - c++

I use application IPCamera on my mobile phone with Android to output (share) video image from it's camera to LAN. I can access it on PC browser - that is ok.
However, I want to make OpenCV capture this video stream from IP address by typing
VideoCapture cap("http://admin:admin#192.168.0.11:8081/?action=stream?dummy=param.mjpg");
while( cap.isOpened() )
{
Mat frame;
if ( ! cap.read(frame) )
break;
cout << "Connected!!";
imshow("lalala",frame);
int k = waitKey(10);
if ( k==27 )
break;
}
and i got error:
Actual codec, which is used by phone is mjpeg (i read it from application on my mobile). I don't know if OpenCV supports this, but is that about mobile application uses some kind of unique codec, or my PC lacks it, or maybe C++/OpenCV code is wrong?

On PC opencv can capture your video stream from your mobile prone..
Like. You are using right connection string, like this for rtsp stream in my case.
VideoCapture capture("rtsp://USER:PASS#xxx.xxx.xxx.xxx/axis-media/media.amp?camera=2");
Probably, You don't have FFMPEG instaled corectly. You need to reinstall Opencv. First you need to install FFMPEG and Opencv After that.
In opencv 3.0.0 and 3.1 try to add
#include <opencv2\videoio.hpp>
#include <opencv2\imgcodecs.hpp>
Some tips how to install ffmpeg and sample in C++ on linux debian Here Code and tips and tricks

Related

Stream OpenCV cv::Mat image to website (html5 page)

I have c++ code running on a raspberry pi using OpenCV to process the camera input (form and color detection). Here is the thread where i capture my images from my pi cam:
(variables names are in french, sorry about that)
Mat imgOriginal;
VideoCapture camera;
int largeur = camPartage->getLargeur();
int hauteur = camPartage->getHauteur();
camera.open(0);
if ( !camera.isOpened() )
{
screen->dispStr(10,1,"Cannot open the web cam");
}
else
{
screen->dispStr(10,1,"Open the web cam");
camera.set(CV_CAP_PROP_FRAME_WIDTH,largeur);
camera.set(CV_CAP_PROP_FRAME_HEIGHT,hauteur);
camera.set(CV_CAP_PROP_FPS,30);
}
while(1)
{
if(largeur != camPartage->getLargeur() || hauteur != camPartage->getHauteur())
{
largeur = camPartage->getLargeur();
hauteur = camPartage->getHauteur();
camera.set(CV_CAP_PROP_FRAME_WIDTH,largeur);
camera.set(CV_CAP_PROP_FRAME_HEIGHT,hauteur);
}
camera.grab();
camera.retrieve(imgOriginal);
camPartage->setImageCam(imgOriginal); //shared object
if(thread.destruction == DESTRUCTION_SYNCHRONE)
{
pthread_testcancel();
}
usleep(20000);
}
Now, i want to stream those images to my website hosted on another raspberry pi. I have looked into gstreamer, ffmpeg and sockets but i didn't find any good example in c++ that worked for me. Im trying to get the lowest latency possible.
Some people suggested to use raspistill but i can't open the camera in another program since its already open by OpenCV.
If you need more information let me know, any help is appreciated.
If you need to stream your camera images from a RPi on the network, There are many approaches to do that, based on your needs.
One approach is to use high-level applications like MJPG streamer, RPi IP Camera, etc.
Another approach is, you can stream camera images throw a network (by RTP, UDP, etc) with GStreamer, FFmpeg, Raspistill, etc. With this approach, you need to have a receiver app to get streams (e.g FFmpeg).
There is also another approach which you already stated in your question and that is directly accessing the camera and capture images then transfer them manually throw network. With this approach, you have more freedom to modify the design (like adding your own compression, encryption, etc) but you should take care of the network protocol by yourself.
In your example, you can transfer each frame in network with a simple TCP/IP socket or you can build up a simple web server. It is obvious that you can't access the cam with two apps at the same time. You can use v4l2loopback to create multiple camera interfaces and access them by multiple apps but it won't solve your problem.
There are good projects like rpi-webrtc-streamer and streameye which uses low-level protocols to transfer images.

Create an RTP/RTSP or HTTP stream using OpenCV frames

I have a custom board which takes input stream from a IP camera and the application perform facial detection using OpenCV on the input video stream.
My use case is to provide an output stream through network which will be accessible through VLC on any device connected in the same network.
I tried writing OpenCV frames through VideoWriter:
VideoWriter outStream("/home/user/frames/frame.mjpg", CV_FOURCC('M','J','P','G'), CAP_PROP_FPS, img.size(), true);
if (outStream.isOpened()){
outStream.write(img);
and creating a stream using mjpg_streamer like:
mjpg_streamer -i "input_file.so -f /home/user/frames" -o "output_http.so -w /usr/local/www -p 5241"
But the above process shows a lot of latency.
I can't use imshow as my hardware does not have any video output port.
Here is my code : https://pastebin.com/s66xGjAC
I would suggest using imwrite(), to save jpeg images in the directory specified by Mjpeg-Streamer. Write low quality Jpegs, set the " CV_IMWRITE_JPEG_QUALITY" to the lowest value that satisfies your requirement.

C++ OpenCV Failed to open webcam on another laptop but able to open on desktop

My program uses OpenCV library to capture a single image from the webcam and then save it onto the local file system.
Currently it is working fine on my desktop; where my program was developed. But when I test it on my laptop (different device), it is unable to detect the webcam.
I went ahead to test it on another laptop, but still the same issue occurs.
Both of the laptop's webcam was not in use when I executed my program, and both laptop has only 1 integrated webcam.
Here are the specifications of the devices and the CMake options for OpenCV.
Desktop
Windows 10 64-bit
External Webcam connected via USB
Webcam exist in Device Manager
Webcam exist in Devices and Printers
Laptop 1
Windows 10 64-bit
On-board Webcam (Integrated)
Webcam exist in Device Manager
Webcam exist in Devices and Printers
Able to access webcam on laptop's "Camera" app
Laptop 2
Windows 10 64-bit
On-board Webcam (Integrated)
Webcam exist in Device Manager
Webcam does not exist in Devices and Printers
Able to access webcam on laptop's "Camera" app
OpenCV CMake
v3.30
BUILD_SHARED_LIBS OFF (Static Libs)
WITH_MSMF ON (Media Foundation Support)
WITH_DSHOW OFF (Tried ON, didn't work, read that it was obsolete)
BUILD_opencv_world ON
Shown below are my codes:
Program Headers
#include <opencv2/opencv.hpp>
void GetDevID();
void OpenDevice(int);
cv::Mat frame;
main
int main()
{
// Initially I tried cv::VideoCapture cap.open(0) for default webcam.
// Unfortunately it only works on my desktop, so I tried opening
// from -1 to 254, hence GetDevID(). Still does not work.
GetDevID();
}
GetDevID - Gets the first device that is opened
void GetDevID()
{
int MaxTested = 254;
int DevID = -2;
for (int i = -1; i < MaxTested; i++)
{
cv::VideoCapture TestDev(i);
bool IsDevOpen = TestDev.isOpened();
TestDev.release();
if (IsDevOpen)
{
DevID = i;
break;
}
}
OpenDevice(DevID);
}
OpenDevice - Opens tested device
void OpenDevice(int DevID)
{
cv::VideoCapture cap;
cap.open(DevID);
if (!cap.isOpen())
{
// This is where it fails when the program is executed on the laptop
// Which means the ID from -1 to 254 is not valid
}
else
{
// Capture 20th frame, for best clarity
for (int i = 0; i < 20; i++)
{
cap.read(frame);
}
cap.release();
if (frame.empty())
{
// Error handling occurs here
}
else
{
// Continues to save file
}
}
}
I am all out of luck on Google, and it seems like OpenCV related issues are quite unique.
So if anyone is able to advice me, would be very much appreciated.
Do let me know if I missed out anything on the question as well.
Edit
It seems that I might have missed out on a few things, as mentioned by DaveS.
The program ran fine on the desktop and laptops, just that whilst it was running on the laptops, it didn't detect any webcam devices, nor did it throw any error codes.
To the program, it was just as if there are no webcam devices connected, but physically, there is.
I have also tested by connecting the external webcam on the laptop, and the program is still unable to find any webcam devices.

Camera connected, but nothing happened, openCV-IP Webcam Android

Here's the deal, I'm trying to interface my S3 as webcam, using IP WebCam app for android, then making a IP webcam within the software, usually the address is http://192.168.1.XX:8080/greet.html maybe the last two digits changes , the webpage give me options and info like this:
"Here is the list of IP Webcam service URLs:
http://192.168.1.XX:8080/video is the MJPEG URL."
The code I'm using is simply like this:
include "opencv2/highgui/highgui.hpp
include "opencv2/imgproc/imgproc.hpp
using namespace cv;
int main(){
VideoCapture cap("http://192.168.1.XX:8080/video.mjpg"); // connect to an ip-cam ( might need some additional dummy param like: '?type=mjpeg' at the end
while(cap.isOpened()){
Mat frame;
if (!cap.read(frame))
break;
imshow("lalala",frame);
int k = waitKey(10);
if ( k==27 )
break;
}
return 0;
}
So the IP WebCam app recognice a connection but there's no image whatsoever... and then it says:
warning: Error opening file <../../modules/highgui/src/cap_ffmpeg_imp
Cannot open the web cam
Process returned -1 <0xFFFFFFF> execution time: 37.259 s
Press any key to continue.
I am using:
Windows 7 Professional
Open CV 2.4.4
Codeblocks 13.12
USB 2.0 webcam 640x480 at 30fps, 50 Hz and all standard.
Try to connect another video streaming android application.
I use Smart WebCam.
open it with
cap.open("http://192.168.1.13:8080/?x.mjpg);

FFMPEG with C++ accessing a webcam

I have searched all around and can not find any examples or tutorials on how to access a webcam using ffmpeg in C++. Any sample code or any help pointing me to some documentation, would greatly be appreciated.
Thanks in advance.
I have been working on this for months now. Your first "issue" is that ffmpeg (libavcodec and other ffmpeg libs) does NOT access web cams, or any other device.
For a basic USB webcam, or audio/video capture card, you first need driver software to access that device. For linux, these drivers fall under the Video4Linux (V4L2 as it is known) category, which are modules that are part of most distros. If you are working with MS Windows, then you need to get an SDK that allows you to access the device. MS may have something for accessing generic devices, (but from my experience, they are not very capable, if they work at all) If you've made it this far, then you now have raw frames (video and/or audio).
THEN you get to the ffmpeg part - libavcodec - which takes the raw frames (audio and/or video) and encodes them into a streams, which ffmpeg can then mux into your final container.
I have searched, but have found very few examples of all of these, and most are piece-meal.
If you don't need to actually code of this yourself, the command line ffmpeg, as well as vlc, can access these devices, capture and save to files, and even stream.
That's the best I can do for now.
ken
For windows use dshow
For Linux (like ubuntu) use Video4Linux (V4L2).
FFmpeg can take input from V4l2 and can do the process.
To find the USB video path type : ls /dev/video*
E.g : /dev/video(n) where n = 0 / 1 / 2 ….
AVInputFormat – Struct which holds the information about input device format / media device format.
av_find_input_format ( “v4l2”) [linux]
av_format_open_input(AVFormatContext , “/dev/video(n)” , AVInputFormat , NULL)
if return value is != 0 then error.
Now you have accessed the camera using FFmpeg and can continue the operation.
sample code is below.
int CaptureCam()
{
avdevice_register_all(); // for device
avcodec_register_all();
av_register_all();
char *dev_name = "/dev/video0"; // here mine is video0 , it may vary.
AVInputFormat *inputFormat =av_find_input_format("v4l2");
AVDictionary *options = NULL;
av_dict_set(&options, "framerate", "20", 0);
AVFormatContext *pAVFormatContext = NULL;
// check video source
if(avformat_open_input(&pAVFormatContext, dev_name, inputFormat, NULL) != 0)
{
cout<<"\nOops, could'nt open video source\n\n";
return -1;
}
else
{
cout<<"\n Success !";
}
} // end function
Note : Header file < libavdevice/avdevice.h > must be included
This really doesn't answer the question as I don't have a pure ffmpeg solution for you, However, I personally use Qt for webcam access. It is C++ and will have a much better API for accomplishing this. It does add a very large dependency on your code however.
It definitely depends on the webcam - for example, at work we use IP cameras that deliver a stream of jpeg data over the network. USB will be different.
You can look at the DirectShow samples, eg PlayCap (but they show AmCap and DVCap samples too). Once you have a directshow input device (chances are whatever device you have will be providing this natively) you can hook it up to ffmpeg via the dshow input device.
And having spent 5 minutes browsing the ffmpeg site to get those links, I see this...