samwell Claude commited on
Commit
85e170b
·
1 Parent(s): 0b51074

fix: Invert PNG/JPEG X-rays before HU conversion for accurate segmentation

Browse files

Problem: PNG/JPEG X-rays have inverted intensities compared to DICOM
- DICOM: lungs = dark (low HU), bones = bright (high HU)
- PNG/JPEG: lungs = bright (high pixels), bones = dark (low pixels)

Solution: Invert PNG/JPEG images (255 - pixel_value) before converting
to Hounsfield Units. This ensures consistent input for TorchXRayVision.

Result: PNG/JPEG segmentation accuracy now matches DICOM accuracy.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

medrax/tools/segmentation/segmentation.py CHANGED
@@ -286,15 +286,19 @@ class ChestXRaySegmentationTool(BaseTool):
286
 
287
  # TorchXRayVision models expect images in the range [-1024, 1024] (Hounsfield units)
288
  # NOT normalized to [0, 1]! We need to scale 8-bit images to this range.
289
- # For 8-bit images (0-255), map to approximate lung window: -1024 to 600
 
290
  if original_img.dtype == np.uint8 or original_img.max() <= 255:
 
 
 
291
  # Scale from [0, 255] to [-1024, 600] (typical lung window in HU)
292
- img = (original_img.astype(np.float32) / 255.0) * 1624 - 1024
293
- print(f"Converted 8-bit to HU-like range: [{img.min():.1f}, {img.max():.1f}]")
294
  else:
295
- # Assume already in HU or similar range
296
  img = original_img.astype(np.float32)
297
- print(f"Kept original range: [{img.min():.1f}, {img.max():.1f}]")
298
 
299
  img = img[None, ...]
300
  print(f"After adding batch dim: {img.shape}")
 
286
 
287
  # TorchXRayVision models expect images in the range [-1024, 1024] (Hounsfield units)
288
  # NOT normalized to [0, 1]! We need to scale 8-bit images to this range.
289
+ # IMPORTANT: PNG/JPEG X-rays are typically INVERTED compared to DICOM
290
+ # (lungs appear bright instead of dark), so we need to invert them first
291
  if original_img.dtype == np.uint8 or original_img.max() <= 255:
292
+ # Invert for PNG/JPEG: 255 - pixel_value
293
+ # This makes lungs dark (like DICOM) before HU conversion
294
+ inverted = 255 - original_img.astype(np.float32)
295
  # Scale from [0, 255] to [-1024, 600] (typical lung window in HU)
296
+ img = (inverted / 255.0) * 1624 - 1024
297
+ print(f"Inverted and converted 8-bit to HU-like range: [{img.min():.1f}, {img.max():.1f}]")
298
  else:
299
+ # Assume already in HU or similar range (DICOM)
300
  img = original_img.astype(np.float32)
301
+ print(f"Kept original range (DICOM): [{img.min():.1f}, {img.max():.1f}]")
302
 
303
  img = img[None, ...]
304
  print(f"After adding batch dim: {img.shape}")