OpenCV VideoCapture works inconsistently - c++

I have been trying to get my application using OpenCV to work for a while now and a longstanding error which I cannot seem to fix is this one:
PROBLEM:
OpenCV's VideoCapture is inconsistent in splitting video into frames for different file formats and codecs.
Specifics:
My errors are in one part of the application: splitting videos into frames. There are three current scenarios when I choose a valid directory for VideoCapture and open it. It either:
Opens and works perfectly.
Is able to open the VideoCapture (cap.isOpened() = true) but receives an empty frame or two during the frame split which causes app to throw error.
Does not open at all.
A given video will only do one of those three things. AVI File formats seem to have most of the errors, though.
Fixes tried:
Installing K-Lite Codec Pack Full
Putting OpenCV_FFMPEG.dll and OpenCV_FFMPEG_64.dll in project directory and in PATH
The only explanation I can think of is this is an error with the way I installed OpenCV and FFmpeg.
Any help would be greatly appreciated! Thanks.
By the way, I am running Qt 5.8.0 and OpenCV 3.2.0 and this is my FrameSplit code.
vector<int> mainFrame::frameSplit(string filename, string location)
{
//Extract + Save Frames
string vidDir = filename;
string locationDir = location + "/frames/";
VideoCapture cap(vidDir);
if (!cap.isOpened())
{
qDebug() << "OO";
return {};
}
else
{
Mat firstFrame;
Mat nextFrame;
Mat frame;
int count = 1;
QProgressDialog progress("Extracting files...", "Abort", 0, cap.get(CV_CAP_PROP_FRAME_COUNT));
progress.setWindowModality(Qt::WindowModal);
progress.setAttribute(Qt::WA_DeleteOnClose, true);
progress.setFixedSize(500, 100);
progress.show();
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
qDebug() << cap.get(CV_CAP_PROP_FRAME_COUNT);
bool failure = false;
for (count = 1; count < cap.get(CV_CAP_PROP_FRAME_COUNT); count++)
{
cap >> frame;
if(frame.empty()) {
QMessageBox messageBox;
messageBox.critical(this, "Error", "There was an error in analyzing the video. Please try and install the appropriate codecs and try again.");
messageBox.setFixedSize(600,400);
vector<int> empty;
return empty;
}
string filePath = locationDir + to_string(count) + ".jpg";
imwrite(filePath,frame,compression_params);
progress.setValue(count);
}
progress.setValue(count);
progress.close();
vector<int> props;
props.push_back(cap.get(CV_CAP_PROP_FRAME_COUNT));
props.push_back(round(cap.get(CV_CAP_PROP_FPS)));
props.push_back(cap.get(CV_CAP_PROP_FRAME_WIDTH));
props.push_back(cap.get(CV_CAP_PROP_FRAME_HEIGHT));
qDebug() << props[0];
return props;
}
}

Related

OpenCV trying to read or write to video file causes VIDEOIO exception "Can't find starting number" (icvExtractPattern)

So for a school project, I am trying to use cv::VideoCapture to open a .avi file to perform some image processing on it. Also, I am trying to record the video from my (Laptop) camera and save it to a file out.avi. Both times I encountered more or less the same exception.
I am using OpenCV 4.1.2 and CLion on Linux Mint.
Trying to use cv::VideoCapture vid(0); works perfectly fine, it shows the output from the Laptop's camera. However, when specifying a path to a video file to open, I get the following error:
VIDIOC_REQBUFS: Inappropriate ioctl for device
[ERROR:0] global /home/aris/dev/opencv/modules/videoio/src/cap.cpp (116) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.1.2-dev) /home/aris/dev/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): ../example_depth.avi in function 'icvExtractPattern'
When trying to create a cv::VideoWriter object (to save the camera video ouput to a file) using:
cv::VideoWriter vidWrit("out.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, cv::Size(width, height), true);
I am encountering this error:
[ERROR:0] global /home/aris/dev/opencv/modules/videoio/src/cap.cpp (392) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.1.2-dev) /home/aris/dev/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): out.avi in function 'icvExtractPattern'
Which looks kind of similar to the other one.
Here is a minimal example (note that the program still shows the camera output in task == "write"):
#include <opencv2/opencv.hpp>
int main ()
{
std::string task = "write";
if(task == "read") { // Read from .avi file
system("pwd"); // Print current path
cv::VideoCapture vid("../example_depth.avi"); // Throws first exception "Inappropriate ioctl for device"
int key = 0;
cv::Mat frame;
while (key != 27) {
vid >> frame;
if (frame.empty())
break;
cv::imshow("Video", frame);
key = cv::waitKey(25);
}
} else if (task == "write") { // Write Laptop video to file
cv::VideoCapture vid(0); // Video from camera
int width = vid.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH);
int height = vid.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT);
cv::VideoWriter vidWriter("out.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, cv::Size(width, height), true); // Throws second exception
int key = 0;
cv::Mat frame;
while (key != 27) {
vid >> frame;
if (frame.empty())
break;
vidWriter.write(frame);
cv::imshow("Video", frame);
key = cv::waitKey(25);
}
}
return 0;
}
I've been looking for a solution for two days now. Maybe I am missing some library or OpenCV didn't get installed correctly, I don't know about that (yes, I've tried 'recompiling' OpenCV). I used this tutorial to make all the OpenCV files.
Did the file you want to write to (out.avi) already exist?
I got this error with opencv-python==4.1.2.30 and changing the output to a filepath that did not exist solved it for me.
I've seen this issue a couple of times. First check if the path to the video is correct. In your case, "out.avi" should exist. So this is probably is a dependency or conflict issue. My speculation is that this error occurs when a backend video encoder library conflicts with OpenCV. Try reinstalling the libraries. I suggest you follow the instructions from the official documentation, and open an issue if you keep experiencing problems.

warning: Error opening file (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:578)

I cannot access ipcamera on opencv, I'm using ipcctrl app to view camera preview and it's working fine, but when I try to paste the URL into my code it displays warning: Error opening file (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:578) what's the problem here ?here is the proof that it is working fine in ipcctrl
cv::Mat imgFrame1;
cv::Mat imgFrame2;
cv::VideoCapture capVideo;
const std::string videoStreamAddress = "http://admin:admin#192.168.8.50:8088/mjpeg.cgi?user=USERNAME&password=PWD&channel=0&.mjpg";
std::vector<Blob> blobs;
cv::Point crossingLine[2];
int carCount = 0;
std::ofstream writer;
writer.open("cars.txt");
writer.close();
capVideo.open(videoStreamAddress);
if (!capVideo.open(videoStreamAddress)) { // if unable to open video file
std::cout << "error reading video file" << std::endl << std::endl; // show error message
_getch(); // it may be necessary to change or remove this line if not using Windows
return(0); // and exit program
}
I already solved this problem, turns out that I have an incorrect URL for the videostream address, the hard part is my camera is not that known and had a little documentations about how to configure it. I used the ispy app to generate a proper URL for my kedacom camera, tested it on VLC and on the app and viola ! it worked.

Video Capture : Frame always empty - opencv

I am working with openCV Version 2.4.9, and on Mac OSX.
I have written this code for loading and displaying a video on my desktop. But it never seems to work. I always get the output as "frame empty". Thus it does not complain about reading the video using VideoCapture.It is NOT able to capture any frames, and thus 'frame' is always EMPTY. Any idea what the problem might be?
Note: I have tried both ways to capture a frame - commented as try 1 and try2.
int main(int argc, const char * argv[])
{
Mat frame;
VideoCapture capture_ir("/Users/shreyatandon/Desktop/resize_ir.avi");
if ( !capture_ir.isOpened() ) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
return -1;
}
for (;;){
// capture_ir.read(frame); //try1
capture_ir>>frame; //try2
if(frame.empty()){
std::cerr<<"frame is empty"<<std::endl;
break;
}
imshow("", frame);
waitKey(10);
break;
}
return 0;
}
Just made it work.
Mat current_frame;
VideoCapture video("video.avi");
while(true)
{
video.read(current_frame);
imshow("Image",current_frame);
}
If you keep having problems using avi format have a look at your links to the ffmpeg libraries and it dependencies. I tried to install it from scratch using homebrew and it is working without problems. Cheers

Unexpected result when Comparing sample image with database of images - Opencv c++

I am working on Image matching program, it captures image from IR camera stores it in one directory. A database of images exist in a different directory. I get an unexpected result while executing. I somehow realize that it's because I'm messing with different directories and something basic. Any help in getting around the mistake? Here's a snippet of the code.
VideoCapture cap(0);
Mat frame;
Mat src, dst, tmp,img_3,img_4;
filename3 = (char *)malloc(sizeof(char));
printf("\n-------------------------------------------------\n");
printf("\nOne to Many Image matching with SURF Algorithm.\n");
printf("\n-------------------------------------------------\n");
//Get the Vein image from Webcam that needs to be compared with the database.
// The below function gets frame and saves it in /home/srikbaba/opencv/veins
veincnt = captureVein(veincnt, cap);
if(veincnt == -1)
cout << "A problem has occured" << endl;
printf("\nPlease enter the filename of saved image with the extension.\n");
scanf("%s",filename3);
//Scan the directory for images.
DIR *dir;
struct dirent *ent;
clock_t tstart1 = clock(); //start clock function, do something!!!!
if ((dir = opendir ("/home/srikbaba/images")) != NULL)
{
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL)
{
if(ent->d_type!= DT_DIR)
{
//Print the images
printf ("%s\n", ent->d_name);
//Store the Filename
img_db = ent->d_name;
//Open each file name as Mat identifier and loop the process
img_3 = imread (filename3, IMREAD_GRAYSCALE);
//Filename3 is saved in /home/srikbaba/opencv/veins --> different directory
// I feel this is the problem
img_4 = imread (img_db, IMREAD_GRAYSCALE);
if( !img_3.data)
{
std::cout<< " --(!) Invalid filename or file not found! " << std::endl;
return -1;
}
Because of this I always get --(!) Invalid filename or file not found message. Is there a way I can compare one image from a directory and another image from a different directory? I hope what I asked is not confusing. Kindly help.
Working on Opencv - C++ on Ubuntu 12.04 LTS
You are getting undefined behavior because you are allocating space for only 1 character for filename3 in the following line:
filename3 = (char *)malloc(sizeof(char));
So in the following line...
scanf("%s",filename3);
Any file name greater than 1 character will invoke undefined behavior.
In my opinion, there is no need of malloc. You can just allocate large enough filename3 of fixed size like this:
char filename3[256];

opencv mp3 header missing

Hi i'm new to the openCV library. Just really installed in today and i was trying to do some basic stuff like show a picture in a window and show a video in a window.
I got both of these to work but when i try and show the video it plays without sound and i get the following
[mp3 # 0x107808800] Header missing
in the console. How do i add the mp3 header so it plays with sound?
here is my code
int main(int argc, const char * argv[])
{
if (argc<2) {
printf("not enough arguments");
return -1;
}
//create a window
namedWindow(windowName,WINDOW_AUTOSIZE);
Mat frame;
//capture video from file
VideoCapture capture;
capture.open(argv[1]);
int run=1;
while (1) {
//make play and pause feature
if (run !=0) {
capture>>frame;
imshow(windowName, frame);
}
char c=waitKey(33);
if (c=='p') {
run=1;
}
if (c=='s') {
run=0;
}
if (c ==27 || c=='q') {
break;
}
}
return 0;
}
you can't .
audio gets discarded (that's the message you get), and there's no way to retrieve it again.