WZMIAOMIAO/deep-learning-for-image-processing · error · ValueError
Image '{}' format not JPEG
Error message
Image '{}' format not JPEG What it means
VOCDataSet.__getitem__ opens each image referenced by a VOC XML annotation and requires its PIL image.format to be 'JPEG'. The dataset assumes VOC-style JPEG images; other formats (PNG, BMP, GIF) cannot pass the standard VOC torchvision-style pipeline (and later transforms may fail on non-RGB data). It throws a ValueError naming the offending image path.
Source
Thrown at pytorch_object_detection/retinaNet/my_dataset.py:56
with open(json_file, 'r') as f:
self.class_dict = json.load(f)
self.transforms = transforms
def __len__(self):
return len(self.xml_list)
def __getitem__(self, idx):
# read xml
xml_path = self.xml_list[idx]
with open(xml_path) as fid:
xml_str = fid.read()
xml = etree.fromstring(xml_str)
data = self.parse_xml_to_dict(xml)["annotation"]
img_path = os.path.join(self.img_root, data["filename"])
image = Image.open(img_path)
if image.format != "JPEG":
raise ValueError("Image '{}' format not JPEG".format(img_path))
boxes = []
labels = []
iscrowd = []
assert "object" in data, "{} lack of object information.".format(xml_path)
for obj in data["object"]:
xmin = float(obj["bndbox"]["xmin"])
xmax = float(obj["bndbox"]["xmax"])
ymin = float(obj["bndbox"]["ymin"])
ymax = float(obj["bndbox"]["ymax"])
boxes.append([xmin, ymin, xmax, ymax])
labels.append(self.class_dict[obj["name"]])
if "difficult" in obj:
iscrowd.append(int(obj["difficult"]))
else:
iscrowd.append(0)
# convert everything into a torch.TensorView on GitHub (pinned to 1ec3fe6f37)
Solutions
- Re-encode the offending image(s) to JPEG with PIL: Image.open(p).convert('RGB').save(p, 'JPEG').
- Batch-convert all non-JPEG files in the dataset directory before training (script over the img_root checking image.format).
- If PNG support is needed, relax the check and convert on load instead of raising: image = Image.open(img_path).convert('RGB').
- Fix filename/annotation mismatches: ensure data['filename'] in the XML points at the real JPEG file.
Example fix
// before
image = Image.open(img_path)
if image.format != "JPEG":
raise ValueError("Image '{}' format not JPEG".format(img_path))
// after
image = Image.open(img_path)
if image.format != "JPEG":
image = image.convert("RGB") # tolerate non-JPEG input Defensive patterns
Strategy: validation
Validate before calling
from PIL import Image
for name in os.listdir(img_root):
with Image.open(os.path.join(img_root, name)) as im:
if im.format != "JPEG":
print("non-JPEG:", name, im.format) Type guard
def is_jpeg(path: str) -> bool:
from PIL import Image
try:
with Image.open(path) as im:
return im.format == "JPEG"
except Exception:
return False Try / catch
try:
sample = dataset[i]
except ValueError as e:
if "format not JPEG" in str(e):
img = Image.open(extract_path(e)).convert("RGB")
img.save(extract_path(e), "JPEG")
else:
raise Prevention
- Batch-verify image formats right after downloading a dataset.
- Never rely on file extensions; check actual image.format.
- Re-encode through PIL/convert('RGB') during dataset preparation.
- Keep annotation filenames in sync with actual image files.
When it happens
Trigger: Iterating the dataset (DataLoader over VOCDataSet) when the file at os.path.join(self.img_root, data['filename']) is not a JPEG: e.g. a PNG renamed to .jpg, a grayscale/CMYK image still saved as PNG, or a mixed-format directory indexed by train.txt.
Common situations: Downloading images from the web where extensions lie; converting a dataset with scripts that copy files without re-encoding; VOC2007/VOC2012 datasets containing some PNG segmentation images mixed into JPEGImages; re-labeling data with annotation tools that save PNG.
Related errors
- image: {} isn't RGB mode.
- dataset have {} classes, but input {}
- dataset have {} classes, but input {}
- image: {} isn't RGB mode.
- image: {} isn't RGB mode.
AI-assisted analysis of WZMIAOMIAO/deep-learning-for-image-processing@1ec3fe6f37 (2026-08-30).
Data as JSON: /api/errors/3ceb7bb0774b8e62.
Report an issue: GitHub.