try...catch for memory full error in imaq toolbox ?
7 次查看(过去 30 天)
显示 更早的评论
Hi,
I am recording data with an usb3vision camera. I am directly capturing to RAM. After a while, the memory of the computer is full and capturing stops. I would like to catch this error and display a msgbox. This is the code I am testing:
clc
imaqreset
delete(imaqfind); %clears all previous videoinputs
hwinf = imaqhwinfo;
info = imaqhwinfo(hwinf.InstalledAdaptors{1});
industrial_camera_name = info.DeviceInfo.DeviceName;
industrial_camera_supported_formats = info.DeviceInfo.SupportedFormats;
industrial_camera_vid = videoinput(info.AdaptorName,info.DeviceInfo.DeviceID,'Mono8');
industrial_camera_settings = get(industrial_camera_vid);
industrial_camera_settings.Source.ExposureTime =20;
industrial_camera_vid.FramesPerTrigger = 10000;
flushdata(industrial_camera_vid);
try
start(industrial_camera_vid);
%wait(industrial_camera_vid);
while industrial_camera_vid.FramesAcquired < industrial_camera_vid.FramesPerTrigger
pause(1)
disp(num2str(industrial_camera_vid.FramesAcquired))
end
catch ME
imaqreset
if strcmpi(ME.identifier,'imaq:imaqmex:outofmemory')
msgbox('Out of memory. RAM is full, most likely, you need to lower the amount of frames to capture to fix this error.','modal');
end
if strcmpi(ME.identifier,'imaq:wait:timeout')
msgbox('Image capture timeout. Most likely, memory is full and you need to lower the amount of frames to capture to fix this error. It is also possible that the synchronization cable is not plugged in correctly.','modal');
end
end
The problem is that the while loop never stops, even if the image capture crashes due to full RAM. How can I stop the while loop and display a proper error message?
This is how my output looks like, the while loop keeps on running:
3870
4031
4192
4353
4514
4675
Error event occurred at 16:38:40 for video input object: Mono8-gentl-1.
Unable to allocate memory for an incoming image frame due to insufficient free physical memory.
Unable to allocate memory for an incoming image frame due to insufficient free physical memory.
Error in memory_full (line 18)
pause(1)
4754
4754
4754
4754
4754
0 个评论
回答(4 个)
Image Analyst
2023-4-3
Perhaps put the try catch INSIDE the while loop. Then in the catch, put a break to kick it out of the loop if an error was thrown.
start(industrial_camera_vid);
while industrial_camera_vid.FramesAcquired < industrial_camera_vid.FramesPerTrigger
try
%wait(industrial_camera_vid);
pause(1)
disp(num2str(industrial_camera_vid.FramesAcquired))
catch ME
% Some error occurred if you get here.
imaqreset
if strcmpi(ME.identifier,'imaq:imaqmex:outofmemory')
uiwait(msgbox('Out of memory. RAM is full, most likely, you need to lower the amount of frames to capture to fix this error.','modal'));
end
if strcmpi(ME.identifier,'imaq:wait:timeout')
uiwait(msgbox('Image capture timeout. Most likely, memory is full and you need to lower the amount of frames to capture to fix this error. It is also possible that the synchronization cable is not plugged in correctly.','modal')));
end
break; % out of while loop.
end
end
9 个评论
dpb
2023-4-3
"I don't understand how, but I'll try to find a way..."
Find the default imagcallback function and look at it -- you'll see it's what is outputting the error messages you're getting; set a breakpoint in it and you'll be able to see the object and data that it receives.
Use the function as a pattern; I think what you'll want to do is to have your replacement return a flag variable that can test inside the while loop and break as @Image Analyst suggests; what the default does is just display the error info to the command window; you need it to do something more than that; return a value that you can check and take action on.
Or, depending upon the needs of the application; you could have it do the stop acquisition and so on there; just that you would then probably(?) need a global parameter to use as the control variable for the while loop to turn it off...just what/how to construct it depends on what is wanted to be done.
Bruno Luong
2023-4-3
To my knowledge there is no simple way to detect memory issue.
What you ask MATLAB, e.g., using command such as
[~,sys] = memory;
membytes = sys.PhysicalMemory.Available; % bytes
I will always report a positive number, even if there is memory runs out since it will swap on HD if you requires MATLAB to allocate array. And when there is NO physical RAM available for instanant the acquisition SW to run correctly there is buffer overrun and it can result crashes. The best thing is to monitor membytes long before and detect when it is no longer reduced and low. It is a sign that the RAM starts to runout and you have to anticipate and stop the acquisition before it crashes.
0 个评论
William Thielicke
2023-4-3
2 个评论
Bruno Luong
2023-4-4
编辑:Bruno Luong
2023-4-4
What surprise me in your log is that the acquisition crashes when free memory is 1.7 Gb. It's a wild guess but it looks to me like the whole video buffer are reallocate each time a new frame arrive. Are you surre the acquisition is called correctly as by the vendor recommendation?
If the buffer is reallocated then you should not monitor the RAM, but the largest contiguous block avalable as dpb suggests.
dpb
2023-4-4
编辑:dpb
2023-4-4
Well, you probably can manage to do it from the above, but it's peculiar as Bruno notes...observe if we take your monitoring data and plot it to see what it looks like ("A picture is worth..." even when collecting images. <vbg>)
s=["Frames captured: 3437, Memory: 3099373568"
"Frames captured: 3482, Memory: 2996944896"
"Frames captured: 3526, Memory: 2891186176"
"Frames captured: 3570, Memory: 2786598912"
"Frames captured: 3615, Memory: 2678345728"
"Frames captured: 3660, Memory: 2572312576"
"Frames captured: 3706, Memory: 2464108544"
"Frames captured: 3752, Memory: 2357243904"
"Frames captured: 3799, Memory: 2248380416"
"Frames captured: 3845, Memory: 2136969216"
"Frames captured: 3892, Memory: 2027577344"
"Frames captured: 3938, Memory: 1915494400"
"Frames captured: 3985, Memory: 1808896000"
"Frames captured: 4002, Memory: 1708388352"];
f=str2double(extractBetween(s,'ed: ',','));
m=str2double(extractAfter(s,'ry: '));
tCapture=table(f,m,'VariableNames',{'Frame','FreeMemory'});
tCapture=addvars(tCapture,[nan;diff(tCapture.Frame)],[nan;-diff(tCapture.FreeMemory)],'NewVariableNames',{'NFrames','MemUsed'});
tCapture.MemPerFrame=tCapture.MemUsed./tCapture.NFrames/1024/1024
yyaxis left
plot(tCapture.Frame,tCapture.FreeMemory/1024^3,'X')
ylabel('Free Memory (GB)')
yyaxis right
plot(tCapture.Frame,tCapture.MemPerFrame,'X')
hAx=gca;
set(hAx.YAxis,{'TickLabelFormat'},{'%0.1f'})
title('Image Capture Memory Useage vs Frame Number')
ylabel('Memory Per Frame(MB)')
xlabel('Frame Number')
We can observe the memory usage is almost perfectly linear with frame number until the very end(*) when the indicated memory usage almost doubled on average. We don't have the data for every image to observe, but one presumes that probably it stayed at the 2MB value until the very last acquired frame and then ran into the allocation problems.
As Bruno, it does seem peculiar that the system still has almost 2GB of overall free memory, but can't seem to find 2MB free; this may indicate some per process limit or other issue with how memory usage is being handled.
(*) Looking at the finer detail, NB the memory per frame is pretty flat until after frame 3800, it then seems more variable for some reason. It's also tantalizing that the first point shown is also lower before the plateau is established after 3500; it would be interesting to observe what the startup transient might look like and if for some reason the application is requiring more memory as it goes along on a per image basis.
We don't know the size/depth of the frame so don't know how this compares to an expected memory footprint.
4 个评论
dpb
2023-4-5
编辑:dpb
2023-4-5
No, I don't have access to the IMAQ TB other than by downloading a trial and then don't have any hardware to use it with, anyway, if did.
But, I think it's conclusive that Bruno hit the nail on the head; the TB acquisition logic is dumb; it allocates the entire buffer including room for a new image every frame and copies the old buffer over and adds a new frame at the end.
2.2M/frame * 4K frames is the 8.8G; when try to double that by allocating a new buffer + new frame to copy the old over to, it exceeds the 16G you have available and dies. Pretty damning evidence that it occurs at almost exactly the 4K number.
This is a grievous fault in the TB design/implementation; it should keep a list structure or some similar way to implement a growing buffer and only add the additional memory for the next frame. There will be some other overhead associated with keeping that data structure, so won't be able to allocate all memory to an image buffer, but certainly could use a very significant fraction of total memory. Of course, then one will run into issues trying to process those later on if actually do completely fill memory, but...
Unless there's a way to preset the number of images wanted to be collected and that will make it allocate the total memory to begin with instead of just free-running???
If not, I'd say this is a quality of implementation issue deserving of a bug/issue report to TMW and it would appear the only choices one would have to collect more frames to memory would be to add memory to the system.
Alternatively, could you stream to disk instead? If your disk is a SSD, performance shouldn't be too bad compared to memory.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!