int main(int argc, char* argv[])
{
VideoCapture cap(0);
Mat current_frame;
Mat previous_frame;
Mat result;
Mat frame;
//cap.open(-1);
if (!cap.isOpened()) {
//cerr << "can not open camera or video file" << endl;
return -1;
}
while(1)
{
cap >> current_frame;
if (current_frame.empty())
break;
if (! previous_frame.empty()) {
// subtract frames
subtract(current_frame, previous_frame, result);
}
imshow("Window", result);
waitKey(10);
frame.copyTo(previous_frame);
}
}
When i run this program to subtract current frame from the previous frame and then show the resultant frame , it show me this error while start executing
Unhandled exception at 0x755d812f in WK01.exe: Microsoft C++ exception: cv::Exception at memory location 0x001fe848..
And i want to apply the same thing on recorded video
in the 1st frame, result is empty !
imshow("Window", result); // this will crash
also, you're copying the empty frame Mat to previous_frame, that should be current_frame instead, no ?
try like:
if (! previous_frame.empty()) {
// subtract frames
subtract(current_frame, previous_frame, result);
imshow("Window", result);
}
waitKey(10);
current_frame.copyTo(previous_frame);
}
I think the problem is with previos_frame. You assign value to previous_frame only at the and of the loop.
I think it might be empty at the start of the while loop, so the
if (! previous_frame.empty()) {
// subtract frames
subtract(current_frame, previous_frame, result);
}
block will not executed.
previous_frame also must be the same size as current_frame when subtracting.
This code(the subtract method) should determine the size of result, what You'd like to show at the following line.
Related
I have a camera application that will display the cameras live stream:
void MainWindow::on_start()
{
if(video.isOpened())
{
video.release();
return;
}
if(!isCameraFound || !video.open(pipeline.trimmed().toStdString(), cv::CAP_GSTREAMER))
{
QMessageBox::critical(this,
"Video Error",
"Must be the correct USB Camera connected!");
return;
}
Mat frame;
while(video.isOpened())
{
video >> frame;
if(!frame.empty())
{
QImage qimg(frame.data,
frame.cols,
frame.rows,
frame.step,
QImage::Format_RGB888);
pixmap.setPixmap( QPixmap::fromImage(qimg.rgbSwapped()) );
ui->graphicsView->fitInView(&pixmap, Qt::KeepAspectRatio);
}
...
And I have a function that does processing and has a loop to inspect the first 250 frames because the camera gives off a specific frame when something is found. But when doing this loop the videostream lags so much it basically freezes until the loop is done. How would I be able to go about removing the lag caused by the frame grabbing loop to be able to go through the loop and have the videostream not lag?
void MainWindow::on_push()
{
Mat test;
for(int i = 0; i < 250; i++){
video >> test;
...
I am facing a weird problem.
I am able to load and show image. Also, I am able to capture image but I cannot see image in display. The camera connected fine and capture image fine but cannot see image.
My system is window 10- 64 bit with opencv 3.3.0.
Code is below.
int main()
{
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "camera didn't connected." << std::endl;
return 0;
}
int nFrame = 0;
cv::Mat image = cv::imread("orgin102.jpg");
cv::imshow("image", image);
cvWaitKey(0);
while (true) {
cv::Mat origin;
cap >> origin;
//flip orign
flip(origin, origin, 1);
nFrame++;
cv::imshow("image", origin);
//if (cv::waitKey(27) >= 0) break;
cvWaitKey(0);
}
return 0;
}
I fixed this problem by changing parameter of cap.
here it is
cv::VideoCapture cap(1);
For some systems, 0 index shows as first camera. and for others index 1 shows first camera.
Hope this helps.
Cheers!
I want to subtract the two successive images taken from the webcam.
as you can see I am doing this inside a while loop. In the last line of the while loop I am setting frame2 = frame and so I can subtract them from the next iteration. But the function cv::subtract returns the above error in the terminal.
what am I doing wrong?
#include <iostream>
#include "core.hpp"
#include "highgui.hpp"
#include "imgcodecs.hpp"
#include "cv.h"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
VideoCapture cap(0); ///open the video camera no. 0 (laptop's default camera)
///make a writer object:
cv::VideoWriter writer;
if (!cap.isOpened()) /// if not success, exit program
{
cout << "ERROR INITIALIZING VIDEO CAPTURE" << endl;
return -1;
}
char* windowName = "Webcam Feed(diff image)";
namedWindow(windowName,WINDOW_NORMAL); ///create a window to display our webcam feed
///we need to define 4 arguments for initializing the writer object:
//filename string:
string filename = "C:\\Users\\PEYMAN\\Desktop\\ForegroundExtraction\\openCV_tutorial\\2.writing from video to file\\Payman.avi";
//fourcc integer:
int fcc = CV_FOURCC('D','I','V','3');
//frame per sec integer:
int fps = 10;
//frame size:
cv::Size framesize(cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT));
///initialize the writet object:
writer = VideoWriter(filename,fcc,fps,framesize);
if(!writer.isOpened()){
cout << "Error opening the file" << endl;
getchar();
return -1;
}
int counter = 0;
while (1) {
Mat frame,frame2,diff_frame;
///read a new frame from camera feed and save it to the variable frame:
bool bSuccess = cap.read(frame);
if (!bSuccess) ///test if frame successfully read
{
cout << "ERROR READING FRAME FROM CAMERA FEED" << endl;
break;
}
/// now the last read frame is stored in the variable frame and here it is written to the file:
writer.write(frame);
if (counter > 0){
cv::subtract(frame2,frame,diff_frame);
imshow(windowName, diff_frame ); ///show the frame in "MyVideo" window
}
///wait for 10ms for a key to be pressed
switch(waitKey(1)){
///the writing from webcam feed will go on until the user presses "esc":
case 27:
///'esc' has been pressed (ASCII value for 'esc' is 27)
///exit program.
return 0;
}
frame2 = frame;
counter++;
}
return 0;
}
Every time you execute the while loop frame2 is created and default initialized. When you call
cv::subtract(frame2,frame,diff_frame);
You are trying to subtract a default constructed Mat from a Mat that has an image in it. These two Mats will not be the same size so you get the error.
You need to move the declaration of frame and frame2 outside of the while loop if you want them to retain their values after each execution of the while loop. You also need to initialize frame2 to the same size or capture a second image into it so you can use subtract the first time through.
You need to declare frame2 outside the scope of the while loop like you did with counter. Right now, you get a fresh, empty frame2 with each iteration of the loop.
You might as well move all the Mats outside the while loop so that memory doesn't have to be de-allocated at the end of each iteration and re-allocated the next, although this isn't an error and you likely won't see the performance penalty in this case.
Also, #rhcpfan is right in that you need to be careful about shallow vs deep copies. Use cv::swap(frame, fram2).
I'm using Visual Studio Express 2013 with OpenCV 2.4.7, following this tutorial.
I have spent hours searching the web for solutions, including all of the relevant SO questions. I have tried:
the return value of VideoCapture::open is 1
extending the waitKey() delay to 50ms and later 500ms
setting the dimensions of the window
creating another project on Visual C++
opening an existing image instead of reading from camera (same error)
but no luck, please help!
Here's my code:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
using namespace std;
using namespace cv;
int main() {
Mat image;
VideoCapture cap;
int camOpen = cap.open(CV_CAP_ANY);
namedWindow("window", CV_WINDOW_AUTOSIZE);
while (true) {
cap >> image;
imshow("window", image);
// delay 33ms
waitKey(33);
}
}
As I compiled and ran it, I got the following error:
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in cv::imshow, file ........\opencv\modules\highgui\src\window.cpp, line 261
Error occurs at the line imshow("window", image);. When I commented it out, there are no complaints.
UPDATES:
A plausible explanation of why this error occured was that my webcam takes time to start, which is why image.empty() is true initially, hence the abort() function was called to exit the program.
With the code
if (!image.empty()) {
imshow("window", image);
}
we can wait for the camera to start
I tried your code and for me it works (it visualizes the current webcam input)!
I ran it on Visual Studio 2012 Ultimate with OpenCV 2.4.7.
...
The error occurs because the image is empty, so try this:
while (true) {
cap >> image;
if(!image.empty()){
imshow("window", image);
}
// delay 33ms
waitKey(33);
}
Maybe the first image you receive from your webcam is empty. In this case imshow will not throw an error. So hopefully the next input images are not empty.
Do this:
VideoCapture cap;
cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
int camOpen = cap.open(CV_CAP_ANY);
Or you can try changing this:
while (true) {
cap >> image;
imshow("window", image);
// delay 33ms
waitKey(33);
}
to
try
{
cap >> image;
imshow("window", image);
waitKey(33);
}
catch (Exception& e)
{
const char* err_msg = e.what();
std::cout << "exception caught: imshow:\n" << err_msg << std::endl;
}
Always check for errors.
You can either enable exception throwing from the VideoCapture instance, or you will have to check manually.
If checking manually, there are two places you need to check:
assert(cap.isOpened()); after creating/opening the VideoCapture instance. If it could not be opened, there is no exception being raised by that. You have to check and handle this. An assertion suffices but you can handle this more gracefully if you want.
if (image.empty()) break; after each cap >> image;, or if (!cap.read(image)) break; instead of cap.read(image);, because the video stream may have ended or there's some issue with the camera. Again, no automatic exception being thrown. You need to check and handle this. The read() may fail intermittently (i.e. next read() works again), but that's rare. Usually, once a read() fails, all following read() calls on that VideoCapture instance will also fail.
There is VideoCapture::setExceptionMode(), which allows read() and open() calls to actually throw exceptions on their own instead of failing silently. In that case, you still have to catch the exception and inspect it (e.what()). If you don't catch and inspect the exception explicitly, the runtime may just print to stderr that some exception occurred, but no details on it.
int i=0;
while(i<4)
{
VideoCapture cap(0); // force camera to open 4 tiMEs
i++;
}
waitKey(5000);
VideoCapture cap(0);
int camOpen = cap.open(CV_CAP_ANY);
namedWindow("window", CV_WINDOW_AUTOSIZE);
while (true) {
cap >> image;
imshow("window", image);
waitKey(33);
}
Do this it will work for you for sure.
I have a grabber which can get the images and show them on the screen with the following code
while((lastPicNr = Fg_getLastPicNumberBlockingEx(fg,lastPicNr+1,0,10,_memoryAllc))<200) {
iPtr=(unsigned char*)Fg_getImagePtrEx(fg,lastPicNr,0,_memoryAllc);
::DrawBuffer(nId,iPtr,lastPicNr,"testing"); }
but I want to use the pointer to the image data and display them with OpenCV, cause I need to do the processing on the pixels. my camera is a CCD mono camera and the depth of the pixels is 8bits. I am new to OpenCV, is there any option in opencv that can get the return of the (unsigned char*)Fg_getImagePtrEx(fg,lastPicNr,0,_memoryAllc); and disply it on the screen? or get the data from the iPtr pointer an allow me to use the image data?
Creating an IplImage from unsigned char* raw_data takes 2 important instructions: cvCreateImageHeader() and cvSetData():
// 1 channel for mono camera, and for RGB would be 3
int channels = 1;
IplImage* cv_image = cvCreateImageHeader(cvSize(width,height), IPL_DEPTH_8U, channels);
if (!cv_image)
{
// print error, failed to allocate image!
}
cvSetData(cv_image, raw_data, cv_image->widthStep);
cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
cvShowImage("win1", cv_image);
cvWaitKey(10);
// release resources
cvReleaseImageHeader(&cv_image);
cvDestroyWindow("win1");
I haven't tested the code, but the roadmap for the code you are looking for is there.
If you are using C++, I don't understand why your are not doing it the simple way like this:
If your camera is supported, I would do it this way:
cv::VideoCapture capture(0);
if(!capture.isOpened()) {
// print error
return -1;
}
cv::namedWindow("viewer");
cv::Mat frame;
while( true )
{
capture >> frame;
// ... processing here
cv::imshow("viewer", frame);
int c = cv::waitKey(10);
if( (char)c == 'c' ) { break; } // press c to quit
}
I would recommend starting to read the docs and tutorials which you can find here.