A preprocessing script that should convert a folder of recorded frames stops before the first image with CAP_IMAGES: can't find starting number (in the name of file): hello/data/raw_data/convert_dataset/* in function icvExtractPattern, ending in f cnt: 0.0. Nothing is wrong with the frames. The image-sequence reader scanned the string it was given, matched zero numbered files, and raised -5:Bad argument. This page decodes the error line by line, ranks the five causes behind it, works the logged case through to its fix, and ends with the naming convention that keeps frame folders loadable.
What the error line tells you
The console output is already a diagnosis. Read it in five parts:
-
VIDEOIO(CV_IMAGES)— the open dispatch incap.cppline 164 chose the image-sequence backend. A string that is not a video container (.avi, .mp4, .mov) and not a device index lands here by design, so a folder path opens the sequence reader instead of failing as file-not-found. -
cap_images.cpp:253— the file and line where the sequence backend reports the failure. -
icvExtractPattern— the function that scans your string for a digit run to fix as the first frame's number. -
(-5:Bad argument)— the open failed on its input string, not on your image data. -
f cnt: 0.0— the frame counter after the scan: zero files matched.
Zero matches means the reader never found a starting number, so it refused to open. Resolution, codec and image content have not been touched yet.
How the sequence reader builds its pattern
The backend accepts two string forms, and both need a number:
- A printf-style pattern with a decimal field, such as
frame_%06d.jpg. The counter starts at 0 with a six-digit field: 000000, 000001, and up to 999999 — 10^6, or 1,000,000 names. - The path of a real numbered file, such as
frame_000001.jpg. The reader takes 000001 as the start and six as the width, then counts upward: 000002, 000003, and on until the next number is missing.
Any string without a digit run — a folder path, a *, a bare stem like frames_ — leaves the pattern empty and the count at 0. That is exactly the logged failure. Two further facts about this backend matter later: it opens every file with IMREAD_UNCHANGED, so frames of different sizes or pixel types are not this error; and the number field breaks past about ten digits.
The table shows what each input form does:
| String you pass | What the reader does | Result |
|---|---|---|
.../convert_dataset/* |
no digits, no pattern, count stays 0 |
-5:Bad argument, f cnt: 0.0
|
.../convert_dataset/ |
folder only, no digits | same error |
.../convert_dataset/frame_000001.jpg |
start = 1, width = 6, counts upward | opens the whole sequence |
.../convert_dataset/frame_%06d.jpg |
counter from 0, six-digit field | opens if frame_000000.jpg exists |
.../clip.avi |
looks like a video, other backend | not this error |
Likely causes, most probable first
1. The string names a folder or a wildcard, not a numbered file. The logged case is exactly this: a dataset-conversion step substituted its input variable, and the reader received hello/data/raw_data/convert_dataset/*. Test: print the string after substitution, before the open call. Fix: pass the first numbered file or a %0Nd pattern.
2. The folder is empty because the upstream step failed. Downloads, archive extraction and frame-generation scripts fail quietly. Test: list the folder from Python and count files whose names contain digits. A count of 0 sends you to the generation step, not the reader.
3. The filenames carry no digits. Hash names and renamed exports give the extractor nothing to anchor on. Test: look for a digit run in the names. Fix: rename with zero-padded indices.
4. The relative path resolves against the wrong working directory. Notebook kernels and shell scripts often run from different directories. Test: os.path.isdir() on the parent folder, then len(os.listdir()) on it; an empty listing means the frames live somewhere else. Fix: absolute paths.
5. The runtime is broken, not the data. One public report of this exact message ended at the installed packages rather than the path: a reinstall cleared it. Test: open a known-good two-file folder. The same message on good files means rebuild or reinstall the library stack.
Worked example: the script that passed convert_dataset/*
Inputs, each with its source:
- Reader input string
hello/data/raw_data/convert_dataset/*— printed in the failing log line of the dataset-conversion step. - Runtime and failure facts: OpenCV 4.6.0, raise at
cap_images.cpp:253, error class(-5:Bad argument), counterf cnt: 0.0— all printed by the same console output. - Backend rules: a pattern needs a digit run or a
%0Ndfield, and the counter reports matched files inf cnt— the sequence reader's documented behavior.
The rule in words: matched files equals the files in the named directory whose names carry a digit run that fits the extracted pattern. The string ends in *, which holds no digits, so no pattern can be extracted and the match count is 0.
The arithmetic, written out:
matches = 0 (from f cnt: 0.0)
starting number = none (needs at least 1 match)
open result = -5:Bad argument (cap_images.cpp:253)
Run the same arithmetic forward on the fix. One real file, frame_000001.jpg, gives at least 1 match, start = 1, width = 6, so the reader can name 000001 through 999999 — a capacity of 999,999 frames, far above any single clip folder.
Decision: f cnt: 0.0 with a wildcard in the input string is a path bug, not a data bug. Fix the string first — pass frame_000001.jpg or frame_%06d.jpg. Re-list the folder; only if the digit-bearing count is still 0 do you go and re-run the upstream generation step.
Fix it in six steps
-
Log the exact string the reader receives, after variable substitution. A trailing
/or*explains the error on its own. -
List the folder from Python, not from your shell, and count the files whose names contain a digit:
import os
d = "hello/data/raw_data/convert_dataset" # illustrative path; substitute yours
names = os.listdir(d) # list of str
numbered = sorted(n for n in names
if any(ch.isdigit() for ch in n))
print(len(numbered), numbered[:3]) # 0 means the frames never got written
-
If that count is 0, re-run the upstream generation step and check its own log and the remaining disk space. The reader has nothing to fix yet.
-
If the count is above 0, open the sequence from the first numbered file.
VideoCaptureandCAP_IMAGESare the library's own names;d,names,numbered,first,cap,okandframeare ours:
import cv2
first = os.path.join(d, numbered[0]) # str, such as .../frame_000001.jpg
cap = cv2.VideoCapture(first) # derives start and width from the name
ok, frame = cap.read() # ok: bool; frame: image array
print(ok) # True proves the sequence opened
-
If you control the naming, prefer a pattern:
cv2.VideoCapture("frame_%06d.jpg")starts counting at 000000. Name the first frame 000000, or keep 000001 and pass the first real file so the start comes from the name. -
Prove the load end to end. Read the whole sequence and compare counts:
n = 0 # int, frames read
while cap.read()[0]:
n += 1
print(n == len(numbered)) # True proves no frame was skipped
A False here with a non-zero n points at names or extensions that do not line up. The pages on why an image sequence imports only its first frame and on JPEG decode hangs on raw pixel data cover the two failure modes that come next.
When the path is right and it still fails
Four rarer causes, each with its tell:
- Numbers wider than the field. The pattern field breaks past about ten digits; keep frame indices to nine digits (999999999) and you stay inside the limit with room to spare.
-
Width that changes mid-sequence. Unpadded names (
frame_1.jpgup toframe_10.jpg) change the digit run's width at 10, which is where matching stops. Zero-pad from the first frame. -
More than one digit run per name.
clip_20240101_frame_0042.jpgoffers the extractor two anchors; keep exactly one. -
Mixed extensions in one folder. The pattern fixes the extension of the first match, so stray
.pngfiles among.jpgframes never get counted. One folder, one extension.
Two checks save time once the sequence does open. Different frame sizes and bit depths across files are not this error: the backend reads each with IMREAD_UNCHANGED, and mismatches surface as conversion errors instead. The pages on validating camera image conversion in Python and on reading the image header bit depth before loading are the next stops there. An image sequence also carries no frame-rate metadata, so a frame-rate query on it returns nothing useful; reading frame rate reliably from OpenCV covers that separately.
Black or empty frames after a clean open move the fault into acquisition and conversion. The stage-by-stage pipeline probe picks that up next. The sibling error when the target is a live camera rather than a folder — Camera failed to initialize — has its own start-sequence fix in camera failed to initialize: fix the start sequence.
The naming convention that prevents it
Write the frames so the reader cannot fail, at the moment the saving program creates them:
- Zero-padded, fixed-width numbers,
%06dfrom 000000. - One digit run and one extension per folder, so the pattern has exactly one way to match.
- Log the written frame count at save time. At load time, read the whole sequence and check read count equals written count before preprocessing continues; that one line turns a silent skip into a loud failure.
- Split long recordings into folders of about 100,000 frames and pass each folder's first numbered file.
The capacity arithmetic is one line:
Six digits hold 1,000,000 names; a folder approaching 999,999 frames should move to %07d and its 10,000,000 names.
Sequences like these come off area scan cameras writing over GigE or USB3, or off frame grabbers capturing CoaXPress and Camera Link lines. The camera finder and the accessories finder filter both by interface, so you can shortlist a recording rig that writes folders you can reload for years.
Quick checklist
- The reader's input string carries a digit run or a
%0Ndfield — never a bare folder or a*. - The folder lists at least one numbered file with the expected extension.
- Frame numbers are zero-padded to one fixed width (000001, not 1).
- One digit run and one extension per folder.
- The folder stays under the field's capacity: 999,999 frames at six digits.
- Read count equals written count before preprocessing starts.
Run this list before any dataset conversion; it is the whole diagnosis on one screen. If the rig that produces the frames is being specced now, the system configurator steps through camera, lens and light in order, and the contact page reaches the applications team.
Questions
Why does a folder path open the image-sequence reader at all?
The videoio layer picks a backend from the shape of the string you give it. A name that is not a video container (.avi, .mp4, .mov) and not a device index falls through to the image-sequence reader, which treats the string as a numbered-image pattern. That is why a folder path produces an image-sequence error rather than a file-not-found message.
Must all frames in the sequence have the same resolution or pixel format?
No. The sequence reader opens every file with IMREAD_UNCHANGED, so resolutions and even pixel types may differ from frame to frame without triggering the starting-number error. Mismatches surface later as conversion or shape errors in your own code, which is why validating each decoded frame right after the open is worth the two lines it costs.
Can I pass a list of file paths instead of a pattern?
Not to the sequence reader; it accepts one string. Either expand the list in your own code and load each path with imread, or group the frames into folders and open each folder's first numbered file. Scripts that build dataset lists usually glob the directory first, then feed the reader one folder at a time.
What does f cnt: 0.0 mean at the end of the error?
It is the backend's frame counter after the pattern scan: zero files matched. The .0 is float formatting, not a partial match. A non-zero count there combined with the same message points at numbers too wide for the field or filenames whose digit runs do not fit the extracted pattern.
How many digits can the frame number have?
Keep it to nine: a nine-digit index reaches 999999999 frames, and the pattern field breaks beyond about ten digits, so nine digits keeps you inside the limit with room to spare. Six digits (up to 999999) is the practical choice for clip folders, and seven digits covers ten million names for long recordings.
My files start at 000001, so why does a %06d pattern fail on the first read?
The pattern form starts counting at 000000, which does not exist in your folder. Either name the first frame 000000, or pass the first real file (frame_000001.jpg) and let the reader derive start number and width from the name. Note also that the read stops at the first missing index; it does not skip ahead over gaps.