OpenCV displaying avi file encoded in I420 - c++

I am trying to write a video processing application using OpenCV 2.4.2 (in Visual C++ 2010 Express on Windows 7) but I am having trouble displaying certain AVI files. Most display correctly, but when I use an AVI file encoded in I420 format all I get is a striped pink image for every frame (it displays correctly in regular media players).
Output displayed: http://i.imgur.com/BOu6c.png?1
Currently, I am using the C++ API, but the same thing happens when I use the C API (code from this page: http://nashruddin.com/how_to_play_avi_files_with_opencv). I find this strange, because in most answers on this site and resources on the web, they explicitly recommend to use the I420 encoding. Does anyone know what could be causing this or how to fix it?
Here is a trimmed down version of the code I am using:
int main(int argc, char** argv){
string fname = "test.avi";
VideoCapture capture(fname);
if(!capture.isOpened()){
cerr << "error opening " << fname << endl;
return -1;
}
Mat frame;
namedWindow("output");
double rate = capture.get(CV_CAP_PROP_FPS);
int delay = 1000/rate;
while(true){
if(!capture.read(frame)) break;
cv::imshow("output", frame);
if(waitKey(delay) >= 0) break;
}
capture.release();
return 0;
}
I am using is the pre-compiled version of OpenCV if that makes a difference (http://sourceforge.net/projects/opencvlibrary/).

Ok, so I managed to test on a few more computers. One just crashed and, on another, the video played fine. It turns out that it was a problem with FFMPEG being enabled in the default OpenCV compilation having problems with the uncompressed AVI. Recompile OpenCV with FFMPEG disabled or just use a different codec to compress the video.

Related

Artefact in read/write (copying) video file using OpenCV

I am trying to read a video frame by frame and process it and write it back to another video file.
Part of the process is to read the video and in another part write it back into another video. I noted that when I am doing this, I am getting some artifacts on the generated video.
The simplest code that I can show the problem is as follow:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <conio.h>
using namespace cv;
using namespace std;
int main()
{
std::string inputFile = "D:\\MyData\\sample2.mp4";
std::string outputFileName = "D:\\MyData\\sample2out.mp4";
VideoCapture inputVideo;
inputVideo.open(inputFile);
VideoWriter videoWritter;
videoWritter.open(outputFileName, inputVideo.get(CAP_PROP_FOURCC), inputVideo.get(CAP_PROP_FPS),Size(inputVideo.get(CAP_PROP_FRAME_WIDTH), inputVideo.get(CAP_PROP_FRAME_HEIGHT)));
while (true) // loop until all frames read. this
{
cv::Mat frame;
// Capture frame-by-frame
inputVideo >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
videoWritter << frame;
}
inputVideo.release();
videoWritter.release();
}
when I run this code, the output video has some artifacts that can be seen in the following image:
I also noted that the size of the output file became a lot larger than the original one ( input file ~ 98 Mbyte and output is around 143 Mbyte).
How can I fix this artifact? why the output size is bigger than the input file when the compression and other parameters are set to be the same?
I am using OpenCV 4.6 and Visual studio 2022 on windows 10.
Edit 1
I run the application on two videos, both of which are downloaded from the internet, one from a site (I can not remember the name of the site but it offers free videos) and the other downloaded from Youtube using a youtube downloader website.
I can share the videos, but I do not know how to upload them to this site. How can I share it?
I can see the same issue in both videos.
If I extract images and save them into a jpeg, the images are correct. but when I encode them into a video I can see the issue.
Edit 2
Sample files are uploaded here: https://www.filemail.com/d/kobthfbkbjanwqm

Capturing from webcam under WinPE?

I am writing a suite of hardware tests that will run in a windows PE environment. I need to test the webcam but so far I am stumped. I compiled a small webcam capture program using the opencv library, but it is unable to detect the webcam. I have tried loading additional drivers, but it hasn't worked. Unfortunately I have not found any help online since apparently no one else is crazy/stupid enough to attempt this. Is this idea fundamentally flawed in some way, or is there a way to do this? Any help is appreciated.
Here is the code I am using that compiles and runs on my windows 10 machine:
#include "opencv2/opencv.hpp"
#include <cstdio>
using namespace cv;
int main(int argc, char** argv)
{
VideoCapture cap;
// open the default camera, use something different from 0 otherwise;
// Check VideoCapture documentation.
if(!cap.isOpened()) // check if we succeeded
{
printf("Unable to open webcam");
return -1;
}
for(;;)
{
Mat frame;
cap >> frame;
if( frame.empty() ) break; // end of video stream
imshow("this is you, smile! :)", frame);
if( waitKey(10) == 27 ) break; // stop capturing by pressing ESC
}
// the camera will be closed automatically upon exit
// cap.close();
return 0;
}
Edit: I realized that the drivers were not loading on startup so I loaded them manually with drvload.exe. Now the webcam shows as functional when I do a WQL query(ConfigManagerErrorCode = 0) but my opencv program will still not detect it.
You won't get your cam to work, without adding some DLLs to your PE environment.
PE is a minimalistic WIndows that misses lots of functions due to minimize memory and diskspace consumption. It is only designed to offline edit Windows images, not to do hardware testing. Ran into similar issues some months ago.
I'm not sure if linking to this project is allowed here, but they sure have helpful information for you on that: TheOven

Reading mp4 (Go Pro) video using OpenCV

I am having difficulty reading in certain video files when using OpenCV with the C++ interface in Visual Studio 2013. I have been able to read in other video formats so believe my code is okay.
The problem video files have been taken using a Go Pro and are mp4. I can play them on the same machine I am using OpenCV on using classic media player. I have used MediaInfo to gather information on the video file:
Format : MPEG-4
Format profile : JVT
Codec ID : avc1
File size : 126 MiB
I have tried providing fourcc codes explicitly using the set function of OpenCV and providing divx as the code and avc1 but with no luck.
My program code is as follows:
int main(int argc, char** argv) {
if (argc != 2) {
help(argv);
system("Pause");
return 1;
}
std::string arg = argv[1];
VideoCapture capture;
capture.set(CV_CAP_PROP_FOURCC, CV_FOURCC('A', 'V', 'C', '1'));
capture.open(arg);
if (!capture.isOpened()) {
cerr << "Failed to open video file!\n" << endl;
help(argv);
system("Pause");
return 1;
}
return process(capture);
}
void help(char** argv) {
cout << "\n TBC" << endl;
}
int process(VideoCapture& src) {
Scalar const LOW_HSV_THRESHOLD(120, 45, 75);
Scalar const HIGH_HSV_THRESHOLD(140, 55, 85);
string windowName[] = { "Original", "HSV", "In Range", "Binary"};
namedWindow(windowName[0], CV_WINDOW_KEEPRATIO);
namedWindow(windowName[1], CV_WINDOW_KEEPRATIO);
namedWindow(windowName[2], CV_WINDOW_KEEPRATIO);
namedWindow(windowName[3], CV_WINDOW_KEEPRATIO);
Mat matOriginal;
Mat matHsv;
Mat matInRange;
Mat dst;
src >> matOriginal;
cvtColor(matOriginal, matHsv, CV_BGR2HSV);
GaussianBlur(matHsv, matHsv, Size(5, 5), 1.5);
cvtColor(matOriginal, matInRange, CV_BGR2GRAY);
threshold(matInRange, dst, 100, 255, THRESH_BINARY);
//inRange(matHsv, LOW_HSV_THRESHOLD, HIGH_HSV_THRESHOLD, matInRange);
imshow(windowName[0], matOriginal);
imshow(windowName[1], matHsv);
imshow(windowName[2], matInRange);
imshow(windowName[3], dst);
waitKey(0);
return 0;
}
}
Any help would be hugely appreciated.
Many Thanks,
Kevin
For documentation purposes, I have expanded my comment as a solution to this problem.
The prebuilt opencv libraries for windows might have not been compiled with ffmpeg support which enables a multitude of video formats to be read.
One quick'n'dirty workaround would be installing ffmpeg and adding it to the windows PATH
environment variable.
The proper solution though, would be building the opencv library from source after installing ffmpeg. This is simplified by using CMake-GUI which allows you easily configure opencv's multiple options such as adding ffmpeg support(USE_FFMPEG flag). Cmake will also generate the Visual Studio project files so you can easily compile the library.
For a more detailed guide check out the video guide on the official opencv documentation page
I found a quicker workaround which happened to work for me:
In the project Release folder (C:\Users\Test\Projects\MyProject\Release) copy the file opencv_ffmpeg2410.dll (2410 comes from the used version of opencv, it might be different for you). Run the project in the release mode in Visual Studio and it could work.
You don't need to do any other modifications: if it can read webcam capture, but not video files, all you have to do is copy opencv_ffmpeg2410.dll into the Release folder of your project (where you might have previously copied other used dll's from opencv's bin folder). Hope it helps.

OpenCV2 codec support

I am reading in video files with openCV, I use the following simple code to do this.
std::string arg = argv[1];
VideoCapture capture(arg); //try to open string, this will attempt to open it as a video file
if (!capture.isOpened()) {
cerr << "Failed to open video file!\n" << endl;
help(argv);
system("Pause");
return 1;
}
I can load and manipulate several videos, but I have problems with others. I imagine this is down to codec issues. I can play the videos using old style win media player, so the codecs are on the system, but I imagine not available in opencv?
Does anyone know what codecs and video format will definitely play on opencv and what is a good option to convert video to these formats?
Many Thanks
Indeed, the supported codec of OpenCV is dependent on your platform and avaible codecs.
This tutorial Creating a video with OpenCV explains the video codec of OpenCV clearly. Though it is meant for writing videos, I think the underlying principle is the same with reading videos.
The function C++: double VideoCapture::get(int propId) can retrieve your loaded video's codec property by setting propId = CV_CAP_PROP_FOURCC. The interpretation of FOURCC can be found on this site. If you have problems with reading .avi videos, it is very likely that the codes is not installed in your platform.

Unable to get Video feed from D-Link DCS 932L using openCv

I am trying to display video feed from IP- Camera(D-Link DCS 932L). I Have gone through topics for the same and tried the code from different posts, but am unable to get the video feed from the camera.
Here's the code which i tried.
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv;
int main(int argc, char *argv[])
{
Mat frame;
namedWindow("video", 1);
String url = "http://admin:admin#172.32.20.55:80/image/jpeg.cgi";
VideoCapture cap(url);
/* VideoCapture cap(0);*/
while ( cap.isOpened() )
{
cap >> frame;
if(frame.empty()) break;
imshow("video", frame);
if(waitKey(30) >= 0) break;
}
return 0;
}
I tried many different kind of url's but i was unable to display any video feed. I thought it might be code problem so I even tried displaying the USB Webcam and it worked. So now i come to conclusion that the problem seems to be with URL which am passing. Heres the list of urls which I tried. I got this Url options from iSpy.Here are those URL's
(JPEG)http://admin:admin#172.32.20.55:80?IMAGE.JPG
(JPEG)http://admin:admin#172.32.20.55:80/image/jpeg.cgi
(MPEG)http://admin:admin172.32.20.55:80/video.cgi?resolution=VGA
(MPEG)http://admin:admin172.32.20.55:80/video/mjpg.cgi
(MPEG)http://admin:admin172.32.20.55:80/mjpeg.cgi? user=admin&password=admin&channel=0
(MPEG)http://admin:pnqadmin172.32.20.55:80/VIDEO.CGI
Please let me know what can be probable problem for displaying the video feed.
Is their something to do with the setting of the OpenCv or something else.Please note that am using VS2010 and C++ Need help of all the Expert out their.
Thanks in advance.
I solved my problem. The problem was with URL. I changed the URL and it worked smooth..!
The URL i used was as follows.
"http://USER:PWD#IPADDRESS:8088/mjpeg.cgi?user=USERNAME&password=PWD&channel=0&.mjpg";
I keep getting the same error:
warning: Error opening file <../../modules/highgui/src/cap_ffmpeg_impl.hpp:529>
I was trying to stream MJPG video from a Foscam IP camera. The URL opened just fine but I couldn't read any frames. May be there was some problem with the video codec.
Here's a hack written in Python that worked for me: https://stackoverflow.com/a/18411168/3183051
Perhaps my answer is too late. Check if opencv_ffmpegXXX.dll or opencv_ffmpegXXX_64.dll (if you are building 64bit executable) is in the same folder where your executable is. Replace XXX with the number of opencv version you use.