cannot convert 'cv::VideoCapture' to 'CvCapture*' - c++

I have a simple program which takes a video and plays it (though it does some image processing on the video). The video can be retrieved from a Dialog Box result, or directly by giving the path of the file. When I use cv::CvCapture capture1, I get the properties like capture1.isOpen(), capture1.get(CV_CAP_PROP_FRAME_COUNT) etc. but when I use CvCapture* capture2 I get weird errors.
I want to use cv::CvCapture capture1 because of my functions are in accordance with capture1. Or is there any way to use both types with some kind of conversion between them like type casting or something else.
Actually I had two programs, the functions of the program1 was for cv::CvCapture and the functions of the program2 was for CvCapture*. I mean the two programs read the video file in different manners.
I then merged these two programs to use some functions from program1 and some functions from program2. But I can't convert cv::CvCapture to CvCapture*.
I am using OpenCv with Qt Creator.
My code is very long to post here but I have simplified my code to make it smaller and understandable. My code may not compile correctly because I modified it to make it simpler.
Any help would be appreciated. Thanks in advance :)
void MainWindow::on_pushButton_clicked()
{
std::string fileName = QFileDialog::getOpenFileName(this,tr("Open Video"), ".",tr("Video Files (*.mp4 *.avi)")).toStdString();
cv::VideoCapture capture1(fileName); // when I use the cv::VideoCapture capture it gives an error
//error: cannot convert 'cv::VideoCapture' to 'CvCapture*' for argument '1' to 'IplImage* cvQueryFrame(CvCapture*)
//CvCapture* capture2 = cvCaptureFromCAM(-1);
// but when i use the CvCapture* capture2, it does not recognize capture2.isOpend() and capture2.get(CV_CAP_PROP_FRAME_COUNT) etc. don't work.
// Is there any way to convert VideoCapture to CvCapture*?
if (!capture.isOpened())
{
QMessageBox msgBox;
msgBox.exec(); // some messagebox message. not important actually
}
cvNamedWindow( name );
IplImage* Ximage = cvQueryFrame(capture);
if (!Ximage)
{
QMessageBox msgBox;
msgBox.exec();
}
double rate= capture.get(CV_CAP_PROP_FPS);
int frames=(int)capture.get(CV_CAP_PROP_FRAME_COUNT);
int frameno=(int)capture.get(CV_CAP_PROP_POS_FRAMES);
bool stop(false);
capture.read(imgsize);
cv::Mat out(imgsize.rows,imgsize.cols,CV_8SC1);
cv::Mat out2(imgsize.rows,imgsize.cols,CV_8SC1);
//I print the frame numbers and the total frames on a label.
ui->label_3->setText(QString::number(frameno/1000)+" / "+QString::number(frames/1000));
ui->label->setScaledContents(true);
ui->label->setPixmap(QPixmap::fromImage(img1)); // here I show the frames on a label.
}

cv::VideoCapture is from the C++ interface of OpenCV, and can be used to capture from a camera device and from a file on the disk
cv::VideoCapture capture1(fileName);
if (!capture.isOpened())
{
// failed, print error message
}
and cvCaptureFromCAM() is a function from the C interface of OpenCV that is used only to capture from a camera device:
CvCapture* capture2 = cvCaptureFromCAM(-1);
if (!capture2)
{
// failed, print error message
}
Don't mix/merge this interfaces together, pick one and stick with it.
If you want to use the C interface to capture from a video file, use cvCaptureFromFile() instead:
CvCapture* capture = cvCaptureFromFile(fileName);
if (!capture)
{
// print error, quit application
}
Check these examples:
Camera capture using the C interface
Camera capture using the C++ interface

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

Unable to read frames from VideoCapture from secondary webcam with OpenCV

Code:
Simple example that works perfectly with primary webcam (device 0):
VideoCapture cap(0);
if (!cap.isOpened()) {
std::cout << "Unable to read stream from specified device." << std::endl;
return;
}
while (true)
{
// retrieve the frame:
Mat frame;
if (!cap.read(frame)) {
std::cout << "Unable to retrieve frame from video stream." << std::endl;
break;
}
// display it:
imshow("MyVideo", frame);
// check if Esc has been pressed:
if (waitKey(1) == 27) {
break;
}
// else continue:
}
cap.release();
Problem:
I have a second webcam, which I'd like to use. However, when I replace VideoCapture cap(0); with VideoCapture cap(1);, the stream is being opened correctly (or at least cap.isOpened() returns true) but the cap.read(frame) call returns false and I'm unable to find out why.
What I've tried:
I've been trying to play with VideoCapture's settings a bit like calling:
cap.set(CV_CAP_PROP_FORMAT, CV_8UC3);
and random stuff like that, but nothing seems to help.
I've also found this: VideoCapture::read fails on uncompressed video (Bug #2281), which seems to be solved on version 2.4.7.. but I've just updated OpenCV to 2.4.8 and it still doesn't work...
I've tried to use the AMCap to capture the raw video from this camera, save it as aaa.avi file and constructed VideoCapture by calling:
VideoCapture cap("aaa.avi");
and it works (while being read from file)... what I need is real-time processing with live view though.
HW, OS, SW details:
My HW: HP ProBook 4510s with built-in webcam that always works perfectly
+ external webcam CANYON CNR-FWCII3, refered by OS as "USB Video Device" (the troublesome one)
OS, SW: Windows 8.1 Pro x86, Visual Studio 2012 Pro, OpenCV 2.4.8 ~ using vc11 build
Questions:
Am I missing something?
Is there anything else that I could do?
Is there at least any way how to retrieve some additional information about what the problem might actually be?
... OpenCV's API seems quite poor in this case and everywhere where people seemed to be facing the similar issue, there was someone claiming it to be "OS / HW depnendant" as an excuse.
Any help will be appreciated.
After some time I've found out that it is always only the first call of read that fails and skipping the first frame started to work fine although the true reason of this behavior remained unknown.
Later James Barnett (see comments above) has pointed out that the reason might be that it takes a while till the camera gets ready for capturing and my current solution looks the following way (C++11's sleep):
#include <chrono>
#include <thread>
...
VideoCapture cap(1);
// give camera some extra time to get ready:
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (!cap.isOpened()) {
std::cout << "Unable to read stream from specified device." << std::endl;
return;
}
while (true)
{
// retrieve the frame:
Mat frame;
if (!cap.read(frame)) {
std::cout << "Unable to retrieve frame from video stream." << std::endl;
continue;
}
// display it:
imshow("LiveStream", frame);
// stop if Esc has been pressed:
if (waitKey(1) == 27) {
break;
}
}
cap.release();
Hopefully some future visitors will find it helpful :)
easiest way to solve is to read once before checking for success. This code snippet works for me.
//
cap.read(frame);
if(!cap.read(frame)){
//
...
the fix in my case is disconect any camera conected to a sub hub! even if is only one! use your pc's usb port directly.

OpenCV - closing the image display window

I am doing on a project for searching through an image database, and when I find the results to some query - 5 database images, I would like to display the results visually. I do not keep all the images in memory, so I have do load the image first in order to display it.
I had something simple in mind, in pseudocode:
for image 1..5
load images
display image in a window
wait for any keypress
close the window
Here's a snippet of my code in C++ using OpenCV for this purpose:
IplImage *img;
for (int i=0; i < 5; ++i){
img = cvLoadImage(images[i].name.c_str(),1);
cvShowImage(("Match" + images[i].name).c_str(), img);
cvWaitKey(0);
cvDestroyWindow(("Match" + images[i].name).c_str());
// sleep(1);
cvReleaseImage(&img);
}
The images array used here does not as such exist in my code, but for the sake of the question, it contains the File Names of the images relative to the current program running point if its name member. I store the image names a bit differently in my project.
The code above almost works: I can iterate through 4/5 images OK, but when last image is displayed and a key is pressed, the image goes gray and I can not close the image window withouth crashing the rest of my application.
My first idea was that becouse of compile-time optimizations, cvReleaseImage releases the image before cvDestroyWindow is finished, and that somehow makes it freeze. But, I've tried adding some waiting time (hence the commented out sleep(1) line of my code) and it didn't help.
I am calling this display functionality from my console application, and when the image freezes, the control returns back to my application and I can keep using it (but the image window is still frozen in the background).
Can you give me any suggestions on how to fix this?
EDIT
I have talked to some people dealing with computer vision and OpenCV on a regular basis since asking the question, and still no ideas.
I have also found a similar stackoverflow question, but there is still no accepted answer. Googleing just gives similar questions as a result, but no answers.
Any ideas on what to try (even if they are not the complete solution) are very much appreciated.
For testing purposes, the application below does exactly what you stated in the question: it loads 7 images through the command line, one by one, and creates a new window for each image to be display.
It works flawlessly with OpenCV 2.3.1 on Linux.
#include <cv.h>
#include <highgui.h>
#define NUM_IMGS 7
int main(int argc, char* argv[])
{
if (argc < 8)
{
printf("Usage: %s <img1> <img2> <img3> <img4> <img5> <img6> <img7>\n", argv[0]);
return -1;
}
// Array to store pointers for the images
IplImage* images[NUM_IMGS] = { 0 };
for (int i = 0; i < NUM_IMGS; i++)
{
// load image
images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED);
if (!images[i])
{
printf("!!! failed to load: %s\n", argv[i+1]);
continue;
}
// display image in a window
cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time
cvShowImage(argv[i+1], images[i]);
// wait for keypress
cvWaitKey(0);
// close the window
cvDestroyWindow(argv[i+1]);
cvReleaseImage(&images[i]);
}
return 0;
}
cvDestroyWindow() usually only starts pretty complicated procedure of window destruction. This procedure requires some interaction (event exchange) between windowing system and your application. Until this procedure finishes, the window cannot be completely destroyed. That is the reason why you see partially destroyed window while your application performs something not related to GUI.
Event exchange may be performed in system-dependent manner. In Windows this means (directly or indirectly) calling GetMessage or MsgWaitFor* functions and processing the result. For Unixes this means (directly or indirectly) calling XNextEvent and processing the result.
OpenCV allows to do this event exchange in system-independent way. There are two documented methods to do this. First one is cvWaitKey() (just call cvWaitKey(1) after you close the last image). Second one is to call cvStartWindowThread() at the start of your program to allow OpenCV updating its windows automatically.
Only one of these methods worked properly on my Linux box with libcv2.1: cvStartWindowThread().
Update (code snippet with cvStartWindowThread())
//gcc -std=c99 main.c -lcv -lcxcore -lhighgui
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include <unistd.h>
#define NUM_IMGS 2
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <img1>\n", argv[0]);
return -1;
}
cvStartWindowThread();
// Array to store pointers for the images
IplImage* images[NUM_IMGS] = { 0 };
for (int i = 0; i < NUM_IMGS; i++)
{
// load image
images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED);
if (!images[i])
{
printf("!!! failed to load: %s\n", argv[i+1]);
continue;
}
// display image in a window
cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time
cvShowImage(argv[i+1], images[i]);
// wait for keypress
cvWaitKey(0);
// close the window
cvDestroyWindow(argv[i+1]);
cvReleaseImage(&images[i]);
}
// cvWaitKey(1);
sleep(10);
return 0;
}
There is no need to destroy the window on each frame, you can simply call cvShowImage() with the same window name and it will replace the current image.
You only need to call destroy window at shutdown. You can use cvCreateWindow() to create the window at startup but it will be created automatically on the first showWindow() call.
In your code, I've seen no calls of cvNamedWindow() to create any of the windows you use to show images on (and that you destroy). You should probably put one of those calls into the loop, before you cvShowImage() (as karlphillip has shown in his answer).
If you create the named windows before the loop: Have you made sure that none of the images have duplicate names? To make sure you don't assign an image to a destroyed window, and to make sure you don't destroy a window that has already been destroyed?
Would omitting all calls of cvDestroyWindow() and using a single call of cvDestroyAllWindows() instead help to avoid your problem?
Did you test that your 5th image is correctly loaded? What about this?
for(...)
{
if(!img)
break;
// display it
}
The problem you encounter sounds like a null pointer to cvShowImage();
I love openCV but it is not the only way to display the search result from your test query. You could write a html file from your c++-code in the root of your image folder and open it in a browser.
If you are running a webserver you could write a simple file list and publish it with a simple php-script or similar.
The resulting html-code would be something like:
<!DOCTYPE html>
<html>
<head>
<style>img {display:block}</style>
<meta http-equiv="refresh" content="5">
</head>
<body>
<img src="subfolderA/img1.png" />
<img src="subfolderB/img2.png" />
<img src="subfolderC/img3.png" />
<img src="subfolderD/img4.png" />
<img src="subfolderE/img5.png" />
</body>
</html>
On advantage of this approach is that it can run on a headless server.
For closing the image display window look at the documentation for opencv2.3:
waitKey (especially notes about events), destroyWindow and this code example based on the image.cpp sample in openCV2.3:
#include "cv.h" // include standard OpenCV headers, same as before
#include "highgui.h"
#include <stdio.h>
#include <iostream>
using namespace cv; // all the new API is put into "cv" namespace. Export its content
using namespace std;
void help(){
cout <<
"\nThis program shows how to use cv::Mat and IplImages converting back and forth.\n"
"Call:\n"
"./image img1.png img2.png img3.png img4.png img5.png\n" << endl;
}
int main( int argc, char** argv ){
help();
namedWindow("Peephole", CV_WINDOW_AUTOSIZE);
int i=0;
while ((argc-1) > i){
i++;
const char* imagename = argv[i];
Ptr<IplImage> iplimg = cvLoadImage(imagename); // Ptr<T> is safe ref-conting pointer class
if(iplimg.empty()){
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
Mat img(iplimg); // cv::Mat replaces the CvMat and IplImage, but it's easy to convert
// between the old and the new data structures (by default, only the header
// is converted, while the data is shared)
if( !img.data ) // check if the image has been loaded properly
return -1;
// it's easy to pass the new matrices to the functions that only work with IplImage or CvMat:
// step 1) - convert the headers, data will not be copied
// this is counterpart for cvNamedWindow
imshow("Peephole", img);
waitKey();
}
destroyAllWindows();
while (1) {
waitKey(10);
}
// all the memory will automatically be released by Vector<>, Mat and Ptr<> destructors.
return 0;
}
If you want to close all OpenCV image display windows
use: destroyAllWindows();
What I was looking for is a solution to check wether a key has been pressed or if the window has been closed. That way python doesn't stall:
"""Check if window closed or key pressed"""
import cv2 as cv
img = cv.imread('image.jpg')
cv.imshow("MyWindow", img)
while cv.getWindowProperty("MyWindow", cv.WND_PROP_VISIBLE) > 0:
if cv.waitKey(1000) > 0:
break
Try using
cvDestroyWindow("Match");
// sleep(1);
cvReleaseImage(&img); // outside the for loop