Reading mp4 (Go Pro) video using OpenCV - c++

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.

Related

imread() still returns empty mat despite correct addressing in openCV 4.0.0

I am newbie to OPENCV.
Now I am trying to display an image using imread(), but imread() doesn't work(keep returning empty mat.) But when I try to draw lines, circles and so on by imread(), it works well.
So I thought there would be something wrong with addressing. And I tried everything I can but it still doesn't work.
And I also have googled a lot of things to solve it, but I can't get any answer to this problem.
What should I do? Is there something wrong I have missed?
I currently use Windows 10, Visual Studio 2017, and openCV 4.0.0 alpha.
Here is my code.
#include <iostream>
#include <opencv2/opencv.hpp>
#ifdef _DEBUG
#pragma comment(lib,"opencv_world400d.lib")
#else
#pragma comment(lib,"opencv_world400.lib")
#endif
using namespace std;
using namespace cv;
int main()
{
Mat image;
image =imread("C:/Users/ymin/source/repos/Project1/Project1/BENZ.bmp",IMREAD_ANYCOLOR);
if (image.empty())
{std::cerr << "Could not open file" << std::endl; return (1);}
imshow("image", image);
waitKey();
return 0;
}
From the OpenCV documentation for imread:
If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix.
This indicates that the file is not there (maybe typo?), you don't have permission to read it, it is in a format not recognized by OpenCV, or it is corrupted.
Make sure the file is where you think it is, and that it is readable, and that OpenCV is compiled to support whatever format the file is in.
(Note that the file extension does not determine its format, you can take a JPEG file and rename it to have a .bmp extension, but it is still a JPEG file.)

OpenCV imwrite() not saving image

I am trying to save an image from OpenCV on my mac and I am using the following code and so far it has not been working.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage);
Can anyone see why this might not be saving?
OpenCV does have problems in saving to JPG images sometimes, try to save to BMP instead:
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.bmp", cvImage);
Also, before this, make sure you image cvImage is valid. You can check it by showing the image first:
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", cvImage);
waitKey(30);
I met the same problem and one possible reason is that the target folder to place your image. Suppose you want copy A.jpg to folder "C:\\folder1\\folder2\\", but in fact when folder2 doesn't exist, the copy cannot be successful(It is from my actual test, not from official announcement). And I solved this issue by checking whether the folder exists and create one folder if it doesn't exist. Here is some code may it help using c++ & boost::filesystem. May it help.
#include <boost/filesystem.hpp>
#include <iostream>
std::string str_target="C:\\folder1\\folder2\\img.jpg";
boost::filesystem::path path_target(str_target);
boost::filesystem::path path_folder=path_target.parent_path();//extract folder
if(!boost::filesystem::exists(path_folder)) //create folder if it doesn't exist
{
boost::filesystem::create_directory(path_folder);
}
cv::imwrite(str_target,input_img);
I also suggest to check folder permissions. Opencv quietly returns from imwrite without any exception even if output folder doesn't have write permissions.
I've just had a similar problem, loading in a jpg and trying to save it back as a jpg. Added this code and it seem to be fine now.
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
And you need to include the param in your writefile.
cv::imwrite("/Users/nickporter/Desktop/Gray_Image.jpg", cvImage, compression_params);
OpenCV 3.2 imwrite() seems to have a problem to write jpg file with Windows Debug mode. I use this way instead of imwrite().
cv::Mat cvImage;
#ifdef DEBUG
IplImage image = IplImage(cvImage);
cvSaveImage("filename.jpg", &image);
#else
cv::imwrite("filename.jpg", cvImage);
#endif
The following function can be dropped into your code to support writing out jpg images for debugging purposes.
You just need to pass in an image and a filename for it. In the function, specify a path you wish to write to & have permission to do so with.
void imageWrite(const cv::Mat &image, const std::string filename)
{
// Support for writing JPG
vector<int> compression_params;
compression_params.push_back( CV_IMWRITE_JPEG_QUALITY );
compression_params.push_back( 100 );
// This writes to the specified path
std::string path = "/path/you/provide/" + filename + ".jpg";
cv::imwrite(path, image, compression_params);
}
Although it is not true for your case. This problem may arise if the image path given as argument to the cv::imwrite function exceeds the allowed maximum path length (or possibly allowed file name length) for your system.
for linux see: https://unix.stackexchange.com/questions/32795/what-is-the-maximum-allowed-filename-and-folder-size-with-ecryptfs
for windows see: https://www.quora.com/What-is-the-maximum-character-limit-for-file-names-in-windows-10

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.

OpenCV displaying avi file encoded in I420

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.

imread not working in Opencv

I'm trying to use the imread function from OpenCV2.2.
My code is very simple.
cv::Mat host= imread("1.bmp", CV_LOAD_IMAGE_GRAYSCALE);
After that, the host matrix became filled by zeros pointers, i.e. an image has not loaded.
If I use cvLoadImage then it all works properly.
The file exists, and I am not mixing the release and debug libraries. Why imread doesn't work?
Reproduced with opencv 2.4.8.
If you are running in Debug, check that you are also using debug libraries, it fixed our problem. : OpenCV imread(filename) fails in debug mode when using release libraries.
i was facing the same problem with 2.4.6 . The reason was that while selecting the library , i had selected both the debug version and the release version. When i selected only the debug version for the library everything worked fine
I can confirm, that there are some problems with imread in OpenCV 2.2. However the problems only occurred on a Windows 32bit system. On a linux and on a mac it worked. I can't tell why it didn't work, but we had a small workaround for that.
We fixed this problem with the following macros, maybe you could try this out and use "ourImread" from then on.
#ifdef WIN32
#define ourImread(filename, isColor) cvLoadImage(filename.c_str(), isColor)
#else
#define ourImread(filename, isColor) imread(filename, isColor)
#endif
I've had the same problem
cv::Mat image= cv::imread("immagine12.jpg"); // Read the file
if(! image.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
cv::waitKey(5000);
return -1;
}
cv::namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Display window", image );
//non so perchè ma senza il waitKey e lasciando solo il system pause non carica l'immagine...
cv::waitKey(5000);
system("pause");
but I fixed it when I inserted the cv::waitKey(5000);
I don't know why but with system pause it can't load the image and it goes on pause after it loads the image!
I have similar problem on Linux, when reading 32 bit tiff images only.
Mat mat= imread(filename, CV_LOAD_IMAGE_ANYDEPTH);
Problem was because OpenCV was not build with Tiff support for some reason.
If you think that it is an OpenCV bug then, please, post your image and instructions for reproducing to the OpenCV bugtracker.
I know it is late but someone might found this helpful. I was facing the same problem while using imread using OpenCV-3.0. I tried all solutions but actually I was not adding the library opencv2/imgcodecs.hpp. Although imshow was working without it, but after I add this I was able to read the image.
Opencv4.3 Windows10 x64 Visual Studio 2019 I finally solved that problem!!!
Ok, now, when you meet the problem, you can try:
Check your settings, make sure you don't mix include .lib file in "Project->Properties->Linker->Input" for Release/Debug, that opencv_xxx430d.lib(note the d) is for Debug, and opencv_xxx430.lib(no d) is for Release, and the platform is x64.
And in C/C++->General, you need to set the Additional include directory that X:/(opencv_build/install)/include and X:/(opencv_build/install)/include/opencv2 respectively for Release/Debug.
Maybe you should #include <opencv2/imgcodecs.hpp>.
Finally, the Unicode Problem, which is also my problem that, the unicode symbol in the image file path, fuck! I don't know why because my code is very normal string path = "D:/kk.jpg(note that, it is / not \) but you can try to debug your code, maybe you can find there is something like path = "?D:/kk.jpg", what the fuck! So don't directly copy/paste your image path, even you've already use the absolute path, you can still meet the unicode problem, so, what you need to do is delete the line of code(string path = "D:/kk.jpg), and then just retype each character one by one! If you're lucky, you will see that image with imshow. Good luck.
see related question here
Please make sure your path is correct ,
According to the Opencv's API , I'd try this call:
arrayMat[i]=imread("1.jpg" , 1 );
The parameters for imread :
Mat imread(const string& filename, int flags=1)
Loads an image from a file.
Parameters:
filename – Name of file to be loaded.
flags – Specifies color type of the loaded image:
>0 the loaded image is forced to be a 3-channel color image
=0 the loaded image is forced to be grayscale
<0 the loaded image will be loaded as-is (note that in the current implementation the alpha channel, if any, is stripped from the output image, e.g. 4-channel RGBA image will be loaded as RGB if ).
Good luck
S
I have the same problem. I solved it. The key is whether the filename has jpg.
If the filename is p1, you should use something like this imread("p1.jpg"). But we often set the filename as p1.jpg, here we should use something like this imread("p1.jpg.jpg").
This also happened to me, my simple solution was to use the C API and then convert to Mat:
IplImage* img = cvLoadImage("c://frame_201.bmp");
Mat mat = Mat(img);
The reverse is also true: if you are building Release and you have Debug libraries, then imread() quietly fails (errno is 0 after imread(), but the image object is not populated).
Another possibility:
If you're on OS X and statically link OpenCV be sure to use libjpeg which is bundled with OpenCV, not the system's one.
I had similar problem with OpenCV 3.0, except that cvLoadImage was not working as well. So, this might not really answer your question, but maybe it will help someone else.
I also had the very same problem that imread didn't work and cvLoadImage did work.
I decided to create a new Visual Studio from scratch and now it works.
There is no general problem with imread in OpenCV 2.4.3 under win32.
I know you want use "imread" & "CV_LOAD_IMAGE_GRAYSCALE" and convert automatically.
But this other way for load one picture and convert to gray scale:
define CV_NO_BACKWARD_COMPATIBILITY
#include <cv.h>
#include <highgui.h>
#include <math.h>
int main(){
/* load the image */
IplImage* img = cvLoadImage("yourPicture.bmp"); //jpg - bmp
/* retrieve properties */
int width = img->width;
int height = img->height;
int nchannels = img->nChannels;
int step = img->widthStep;
IplImage* img2 = cvCreateImage(cvSize(img->height, img->width),IPL_DEPTH_8U,1);
/* setup the pointer to access image data */
uchar *data = ( uchar* )img->imageData;
uchar *data2= ( uchar* )img2->imageData;
/* convert to grayscale manually */
int i, j, r, g, b, byte;
for( i = 0 ; i < height ; i++ ) {
for( j = 0 ; j < width ; j++ ) {
r = data[i*step + j*nchannels + 0];
g = data[i*step + j*nchannels + 1];
b = data[i*step + j*nchannels + 2];
byte = ( r + g + b ) / 3;
int v0=0, v1=0, v2=0;
data2[i*(img2->widthStep)+j*(img2->nChannels)+0] = byte;
data2[i*(img2->widthStep)+j*(img2->nChannels)+1] = byte;
data2[i*(img2->widthStep)+j*(img2->nChannels)+2] = byte;
}
}
cvNamedWindow("ImagenColor", 1);
cvShowImage("ImagenColor", img);
cvNamedWindow("Gray", 1);
cvShowImage("Gray", img2);
}