You are grabbing a fixed number of frames from a live camera and want them as data, not as twenty image files you read back afterwards. The direct answer: yes, keep every frame in one numeric array in memory. Preallocate a height × width × channels × n array of type uint8, assign each getsnapshot result into one slice, and the whole sequence lives and dies in RAM with no imwrite call anywhere. This page gives you the memory math to size that array before capture, the loop that fills it, a test that proves the buffer holds what you expect, and the point at which files genuinely become the better tool.
The decision: one preallocated array, no files
getsnapshot returns a finished frame as plain numeric data — an H-by-W-by-3 uint8 array for RGB, already in your workspace. Writing frames to disk inserts encoding, naming, read-back and decoding between capture and processing, and none of that serves your algorithm. Keep the sequence in one 4-D array indexed by frame number, and every later operation — display, averaging, differencing, exporting one frame — is a slice access at RAM speed. The same no-disk principle is what camera module image acquisition without saving files applies to embedded modules.
Size the buffer before the loop starts:
For RGB frames held as uint8, channels is 3 and bytes per channel is 1, so the buffer costs 3 × n bytes for every pixel of one frame. One allocation up front means each captured frame costs one assignment, and nothing else moves.
What you need
- A running video input object, so frames are being delivered while the loop turns. Create and start it for your camera first; the acquisition side is covered in continuous camera acquisition mode for live image loops.
- A frame count fixed in advance: n = 20 in the worked example below. The array is sized once, so grab-until-something-happens needs an event-driven design instead.
- One probe frame to read the true size from: call
getsnapshotonce and run[h, w, c] = size(frame). The frame is uint8; c is 3 for RGB and 1 for a monochrome camera. - Free RAM of at least width × height × c × n bytes. The worked example and the 12 MP case below give you the two reference points.
Worked example: 20 VGA frames need 18,432,000 bytes
The inputs, and where each comes from: n = 20 frames (the capture count the task sets); 640 × 480 pixels per frame (the RGB mode a typical webcam defaults to); 3 channels per pixel; 1 byte per channel, because getsnapshot returns uint8.
The rule in words: buffer bytes = width × height × 3 × n.
The result is one uint8 array of 18,432,000 bytes, and the decision follows from the size: keep it in RAM. Twenty frames of VGA video are under 20 MB of memory; writing files would add encoding and read-back while buying nothing. The same loop holds 200 frames in 184,320,000 bytes (about 176 MiB) before memory planning needs to start.
Steps: preallocate, fill, verify
- Fix n and start the camera. Frames must be flowing before the loop turns, so start the video input object first, then run the loop below.
- Probe one frame and read its true size with
size(frame). Never type the dimensions from memory; another capture mode changes them, and the first assignment fails. - Allocate the buffer once:
frames = zeros(h, w, c, n, 'uint8'). One call, one contiguous block, class uint8 to match the frames exactly. - Fill one slice per iteration:
frames(:,:,:,i) = getsnapshot(vid). Nothing in the loop touches the disk. - Verify the buffer before you trust it, then use it: check the whos report, assert size and class, display any slice.
The loop in full; frame and frames are uint8 arrays, and n, i, h, w and c are scalars:
n = 20; % frames to keep
frame = getsnapshot(vid); % uint8 probe frame
[h, w, c] = size(frame); % 480, 640, 3 for VGA RGB
frames = zeros(h, w, c, n, 'uint8'); % 18,432,000 bytes
for i = 1:n
frames(:,:,:,i) = getsnapshot(vid); % one slice per grab
end
The test that proves the result is two checks and one view:
whos frames
% Name Size Bytes Class
% frames 480x640x3x20 18432000 uint8
assert(isequal(size(frames), [h, w, c, n]))
assert(strcmp(class(frames), 'uint8'))
imshow(frames(:,:,:,5)) % frame 5, straight from RAM
If whos reports 18,432,000 bytes and class uint8, the buffer holds exactly the 20 RGB frames the arithmetic promised. From here, mean(frames, 4) collapses the sequence into one average image, and any function that accepts a uint8 image accepts a slice.
The same math at 12 MP and 120 fps
Industrial cameras hand your process the same kind of frame — an H-by-W-by-3 uint8 array — just bigger and faster. Area scan cameras and board-level cameras both end at a numeric frame in memory; what changes is the call that returns it and the size you allocate.
- Sensor format
- 1/1.7"
- Interface
- USB3
- Resolution
- 12 MP
- Shutter
- Rolling
The LS-CMR-0166 delivers 4000 × 3000 frames at 30 fps over USB3. One RGB frame is 4000 × 3000 × 3 = 36,000,000 bytes (34.3 MiB), so the 20-frame buffer from the worked example grows to 720,000,000 bytes, about 687 MiB. At 30 fps those 20 frames span 20/30 = 0.67 s. The buffer stays comfortable; scale n to the free RAM you can spare, because 100 frames already claim 3.6 GB.
- Sensor format
- 1/1.8"
- Lens mount
- C-mount
- Interface
- USB3
- Resolution
- 5 MP
The LS-BCM-0003 is a 3.1 MP board-level camera with an IMX252 sensor and a global shutter, streaming 120 fps over USB3. The rate turns the arithmetic sharp: one RGB frame is about 3,100,000 × 3 = 9,300,000 bytes, so the stream carries 9,300,000 × 120 = 1,116,000,000 bytes per second, roughly 1.1 GB/s. Writing that to disk frame by frame outruns ordinary storage, but 20 frames — 186,000,000 bytes, 0.17 s of video — buffer instantly in RAM. Grab everything while the event runs, then write or process afterwards; retrieving multiple images from the camera buffer for later processing works through that grab-now, handle-later pattern.
When writing files is the right call
Files win in three cases, and the arithmetic tells you which:
- Sequences that outgrow RAM. One minute of 12 MP RGB at 30 fps is 36,000,000 × 30 × 60 = 64,800,000,000 bytes, about 64.8 GB. No in-RAM buffer holds that; write frames as they arrive, or shrink the region of interest or the frame rate until the buffer fits.
- Frames headed for other tools or people. Files are the interface there; export after the capture loop so the loop time stays constant.
- Sequences kept between sessions. One array written to a single data file reloads in one call, faster than reading twenty images; reading image header bit depth before loading files matters once files from different cameras mix.
Whichever way you write, a failed grab can hand you an empty frame, and the empty-image failure when writing frames shows what that looks like and how to fix the frame first.
Common mistakes that cost memory or frames
- Growing the array inside the loop.
frames(:,:,:,end+1) = getsnapshot(vid)forces a reallocation and a full copy on every frame. Appending n frames this way moves 1 + 2 + … + n ≈ n²/2 frames' worth of bytes: at 36,000,000 bytes per 12 MP frame, appending 100 frames copies about 5050 × 36 MB = 181,800 MB, roughly 182 GB, to buffer a capture that is only 3.6 GB. - Allocating in the wrong class. getsnapshot hands you uint8, 1 byte per channel; a buffer created without the uint8 class lands as double at 8 bytes per channel. The 18,432,000-byte example buffer becomes 147,456,000 bytes — 8× the memory for identical frames, plus display routines that expect uint8 input.
- Assuming the frame size. A camera switched from 640 × 480 to 1280 × 720 delivers 921,600 pixels and 2,764,800 bytes per RGB frame, so 20 frames need 55,296,000 bytes (52.7 MiB) instead of 18,432,000, and the undersized assignment fails on frame 1. Read the size from a probe frame every run.
- Processing between grabs. Any work inside the capture loop steals from the frame budget; at 120 fps that budget is 1000/120 = 8.3 ms per frame. Grab all n frames first and process the array afterwards.
Next step
Size the buffer from the frame size your camera actually delivers, then pick hardware that matches the rate the task needs. The camera finder filters by interface, resolution and shutter, and the camera configurator walks the whole chain. When there is no PC in the loop at all, smart cameras run this capture-and-buffer pattern on the device. To check the math against a specific camera before ordering, contact the applications team.
Questions
How many frames fit in one in-memory buffer?
Size it from bytes = width × height × 3 × n. At 640 × 480, one RGB frame is 921,600 bytes, so 2,000 frames need 1,843,200,000 bytes, about 1.8 GB. At 4000 × 3000, one frame is 36,000,000 bytes, so 100 frames need 3.6 GB. Keep the total well inside the free RAM on the capture machine, because the processing code needs room in the same pool.
Why does my stored frame have two dimensions instead of three?
The camera is delivering monochrome frames, so getsnapshot returns an H-by-W uint8 array with no channel dimension. Allocate zeros(h, w, 1, n, 'uint8') instead and the same fill loop works unchanged. Reading size(frame) before allocating is what catches this: a wrong assumption about the channel count surfaces as a size error on the first assignment instead of silent data loss.
Can I still export single frames to files afterwards?
Yes. Index one slice — frames(:,:,:,i) — and write it directly; the slice already is image data, so there is no read-back step. Export after the capture loop finishes, which keeps the loop time constant and lets you pick the format once you know which frames matter. Choose a lossless format whenever the pixels will be measured rather than viewed.
Does preallocation matter for a short capture like 20 small frames?
Barely, but the habit matters. Appending 20 VGA frames by concatenation copies 1 + 2 + … + 20 = 210 frames' worth of pixels, about 193,536,000 bytes — tolerable once, painful in a repeated loop. The same habit at 100 large frames turns a one-second grab into a multi-second stall, so preallocate even when the small case forgives you.
Does this pattern work with industrial cameras, not just webcams?
Yes. Any camera whose SDK hands your process an H-by-W-by-3 uint8 frame supports it: probe one frame, read its size, preallocate, assign slices. GigE and USB3 area scan cameras, board-level cameras and smart cameras all reduce to a numeric frame in memory; only the function that returns the frame and the dimensions you allocate change.

