I have this short C++ program which takes snapshot images from a camera in a loop and displays them:
void GenericPGRTest::execute()
{
// connect camera
Camera *cam = Camera::Connect();
// query resolution and create view window
const Resolution res = cam->GetResolution();
cv::namedWindow("View");
c = 0;
// keep taking snapshots until escape hit
while (c != 27)
{
const uchar *buf = cam->SnapshotMono();
// create image from buffer and display it
cv::Mat image(res.height, res.width, CV_8UC1, (void*)buf);
cv::imshow("Camera", image);
c = cv::waitKey(1000);
}
}
This uses a class (Camera) for camera control I created using the Point Grey SDK and functions from the OpenCV library to display the images. I'm not necessarily looking for answers relating to the usage of either of these libraries, but rather some insight on how to debug a bizarre problem in general. The problem is that the application freezes (not crashes) on the cam->SnapshotMono() line. Of course, I ran through the function with a debugger. Here is the contents:
const uchar* Camera::SnapshotMono()
{
cam_.StartCapture();
// get a frame
Image image;
cam_.RetrieveBuffer(&image);
cam_.StopCapture();
grey_buffer_.DeepCopy(&image);
return grey_buffer_.GetData();
}
Now, every time I step through the function in the debugger, everything works OK. But the first time I do a "step over" instead of "step into" SnapshotMono(), bam, the program freezes. When I pause it at that time, I notice that it's stuck inside SnapshotMono() at the RetrieveBuffer() line. I know it's a blocking call so it theoretically can freeze (no idea why but it's possible), but why does it block when running normally and not when being debugged? This is one of the weirdest kinds of behaviour under debugging I've seen so far. Any idea why this could happen?
For those familiar with FlyCapture, the code above doesn't break as is, but rather only when I use StartCapture() in callback mode, then terminate it with StopCapture() before it.
Compiled with MSVC2010, OpenCV 2.4.5 and PGR FlyCapture 2.4R10.
Wild guess ... but may it be that StartCapture already starts the process that
ends up with having the buffer in ìmage, and if you step you leave it some
time until you get to RetrieveBuffer. That's not the case if you run it all at once ...
Related
I am writing a Qt program using matlab dll, the matlab function is very simple, However I encountered some exception caused by initializing problem. So I have changed my part of code as below.
void DicomViewer::on_pushButton_clicked()
{
if(libMyAddInitialize()){
mwArray dicomArray2=Mat2mwArray(dicomMat1);
//c_matlab(1,dicomArray2,Mat2mwArray(dicomMat1));
mwArry2Mat(dicomArray2).copyTo(dicomMat2);
dicomImgShow(TEMPDICOM2);
libMyAddTerminate();
}
}
This part of the code provides a button to change my cv::Mat data. I am using two functions Mat2mwArrayandmwArray2Mat to convert Mat between mwArray. Funciton dicomImgShow is to show the Mat to My program. That I think code is not the key problem.
My Key problem is The button function only work in my local disk (C:/ and D:/). I put it into my U disk and it failed. I also tried to run it in admin mode, but failed again. So I wonder what's wrong in my program.
Thanks for anyone who come to help .
I'm writing a Qt program (using Qt 5.4) that reads frames from a webcam based on a QTimer, not a separate thread (interval set to 20 ms, of course it takes much longer than 1/50 of a second to read a frame from the webcam and process it, I'd approximate the frame rate is perhaps 20 fps. Anyhow, the function which runs when the timer cycles is a slot and is as follows:
///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {
bool blnFrameReadSuccessfully = capWebcam.read(matOriginal); // get next frame from the webcam
if (!blnFrameReadSuccessfully || matOriginal.empty()) { // if we did not get a frame
QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
QApplication::quit();
}
// process frame here . . .
The idea being if the webcam can be successfully read at the beginning of the program, but then cannot be (webcam stops working, user accidentally disconnects webcam, etc.) the program should show a message box to this effect and then close itself entirely.
With the above, if I unplug the webcam while the program is running for testing purposes, the message box appears as intended, but after choosing OK, a debug error screen appears. If I choose "Abort" the form is still there and will not respond. After attempting to close the form multiple times Windows asks "the program does not seem to be responding, would you like to close?" at which time I can close the form. Clearly this is not achieving the intended effect.
After various Googling I found the suggestion to modify as follows:
///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::closeEvent(QCloseEvent *) {
QApplication::quit();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {
bool blnFrameReadSuccessfully = capWebcam.read(matOriginal); // get next frame from the webcam
if (!blnFrameReadSuccessfully || matOriginal.empty()) { // if we did not get a frame
QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
closeEvent(new QCloseEvent());
}
// process frame here . . .
When I first saw this code I was optimistic, however it gives me the same result as above (program hangs with the form still open). I'm using OpenCV 2.4.11 for my image processing and my program has 4 files:
frmmain.h (.h for the main form, which is a standard QMainWindow made with Qt Creator)
frmmain.cpp (.cpp for the main form, where the above code resides)
main.cpp (which I have not changed from how Qt Creator made it)
frmmain.ui (typical form with a small number of common widgets added via Qt Creator)
Yes, I realize that I could show an error message on one of the widgets that can show text, return from the function, and leave it to the user to close the program, but I'm looking for a more elegant solution. Can anybody offer further advice as to how to fully close a graphical Qt program? Please advise.
Two things that could possible solve your problem:
Before displaying the messagebox, stop the timer with the stop() method.
After the QApplication::quit(); exit the function with return; Your function might be running to the end one last time and accessing invalid objects.
For anybody else's reference Rafael Monteiro's answer was spot on. Here is the updated code (verified working):
///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::closeEvent(QCloseEvent *) {
if(qtimer->isActive()) qtimer->stop(); // had to stop timer here !!!!!!!!
QApplication::quit();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void frmMain::processFrameAndUpdateGUI() {
bool blnFrameReadSuccessfully = capWebcam.read(matOriginal); // get next frame from the webcam
if (!blnFrameReadSuccessfully || matOriginal.empty()) { // if we did not get a frame
QMessageBox::information(this, "", "unable to read from webcam \n\n exiting program\n");
closeEvent(new QCloseEvent());
return; // had to add return here !!!!!!!!!
}
// rest of function here . . .
I should mention I had to add both the return and stop the timer. Thanks Rafael!
This is driving me up the wall..
I've got a very simple SDL2 program.
It has a array of 3 SDL_Texture pointers.
These textures are filled as follows:
SDL_Texture *myarray[15];
SDL_Surface *surface;
for(int i=0;i<3;i++)
{
char filename[] = "X.bmp";
filename[0] = i + '0';
surface = SDL_LoadBMP(filename);
myarray[i] = SDL_CreateTextureFromSurface(myrenderer,surface);
SDL_FreeSurface(surface);
}
This works, no errors.
In the main loop (which is just a standard event loop waiting for SDL_QUIT, keystrokes and a user-event which a SDL_Timer puts in the event queue every second) I just do (for the timer triggered event):
idx = (idx+1) % 3; // idx is global var initially 0.
SDL_RenderClear(myrenderer);
SDL_RenderCopy(myrenderer, myarray[idx], NULL, NULL);
SDL_RendererPresent(myrenderer);
This works fine for 0.bmp and 1.bmp, but the 3rd image (2.bmp) simply shows as a black field.
This is structural.
If I alternate the first 2 images they are both fine.
If I alternate the 2nd and 3rd image the 3rd image doesn't show.
If I use more than 3 images then 3 and upwards show as black.
Loading order doesn't matter. It starts going wrong with the 3rd image loaded from disk.
All images are properly formatted BMP's.
I even saved 2.bmp back to disk under a different name by using SDL_SaveBMP() after it was loaded to make sure it got loaded in memory OK. The new file is bit for bit identical to the original.
This program, without modifications and the same bmp files, works fine on OSX (XCode5) and Windows (VC++ 2012 Express).
The problem only shows on the Raspberry PI.
I have placed explicit error checks on every call that can leave a result/error-code (not shown in the samples above for brevity) but all of them show "no error".
I have used the latest stable source set of www.libsdl.org and compiled as instructed (configure, make, make install, etc.).
Anybody got any idea what could be going on ?
P.S.
Keyboard input doesn't seem to work either on my PI, but I haven't delved into that yet.
Answering myself as I finally figured it out myself...
I finally went back to the README-raspberrypi.txt that came with the SDL2 sources.
I didn't read it carefully enough the first time around...
Problem 1: I'am running on a FULL-HD display. The PI's default GPU memory is 64MB which is not enough for large displays and double-buffering. As suggested in the README I increased this to 128MB and this solved the black image problem.
Problem 2: Text input wasn't working because my user-account was not in the input group. I had added the default "pi" account to the input group initially, but when I later started using another account I forgot to add that user to the group.
In short: Caught by my own (too) quick skimming of the documentation.
First of all, excusme for my bad English. I am working in it.
I am working in a computer vision application. I am using a webcam. The main loop is like this:
while true
get frame
process frame
show frame in figure
end while
And I want something like this:
while figure is open
get frame
process frame
show frame in figure
end while
I used to use figure and imshow for plot the frame, and I used handlers for knowing when the figure is closed by the user.
fig = figure;
set(fig,'KeyPressFcn','exit = true;');
set(fig,'CloseRequestFcn', 'exit = true; delete(gcf)');
But now I am using the vision.VideoPlayer from the Computer System Toolbox because is faster, and I can not find a way to do some similar. I don't want to use a GUI.
The code is this (from this other thread):
vid = videoinput('winvideo', 1, 'RGB24_320x240'); %select input device
hvpc = vision.VideoPlayer; %create video player object
src = getselectedsource(vid);
vid.FramesPerTrigger =1;
vid.TriggerRepeat = Inf;
vid.ReturnedColorspace = 'rgb';
src.FrameRate = '30';
start(vid)
%start main loop for image acquisition
for t=1:500
imgO=getdata(vid,1,'uint8'); %get image from camera
hvpc.step(imgO); %see current image in player
end
Some idea?
You can find the figure handle of vision.VideoPlayer object by turning on "ShowHiddenHandles".
set(0, 'ShowHiddenHandles', 'on') % Revert this back to off after you get the handle
After this gcf can give you the handle. But it is risky to change callbacks for hidden handles. They might already have many of their callbacks set for proper functioning of VideoPlayer object. You might want to check for their validity and visibility to detect whether it is open.
h = gcf;
...
ishandle(h)
get(h, 'Visible') % will return 'off' if the figure is not visible.
I am writing a program that uses OpenCV and involves intrinsic and distortion parameters. These parameters are loaded from .xml files saved on disc. I use the following commands in my opening declarations to load the files:
CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml");
CvMat *distortion = (CvMat*)cvLoad("Distortion.xml");
This works fine as long as the files are in the program's working directory. When they are not, the program crashes without any indication of the nature of the error. I have made the mistake of not having the xml files located correctly multiple times before, and I would like to make this easier to troubleshoot in the future.
I would like to create a guard against the files failing to load. Perhaps if they are not present my program could display an error message and exit gracefully. I saw the method suggested here, and it should work for me, but I was wondering if there was a cleaner way to do it without including another header.
For example, the OpenCV function cvQueryFrame returns 0 if it does not return a frame. I use the code
frame = cvQueryFrame(capture);
if(!frame)
{
printf("ERROR: Could not get frame from webcam.");
exit(-1);
}
to exit the program if cvQueryFrame fails to return a frame. I would like to do something similar with my matrix loading commands. Is this possible, and if so, how should I do it?
I checked the OpenCV documentation and could not find a description of cvLoad's behaviour when it cannot find the file specified so I am not sure how to proceed.
I am writing this project in C++ and running it on Windows 7.
It works. Go ahead and try it yourself:
CvMat *distortion = (CvMat*)cvLoad("Distortion.xml");
if (!distortion)
{
printf("!!! cvLoad failed");
exit(-1);
}