【疑难杂症2025-001】反片图像校正为正片后,图像显示黑屏的问题

本文由Markdown语法编辑器编辑完成.

1. 背景:

近日遇到了某家医院的一些胸部DR的图像.用一般的dicom软件打开后,显示是反片状态.
也就是,高密度区域是黑色; 低密度区域是白色.
这个和一般的DR, CT图像,是相反的.

一般的DR, CT图像,由于背景是空气,密度比较低,所以呈现为黑色; 有器官,肌肉和骨骼的地方,都是亮色, 即不同程度的白色.

那么,是什么tag来控制这个图像是反片,还是正片呢.是一个名叫:Photometric Interpretation.
关于这个tag的解释,可以从网站上查询得到:

在这里插入图片描述
它是一类标签: Required(1),也就是说,医学图像,必须有这个tag, 且有值.
它的枚举值,最常见的是: MONOCHROME2, MONOCHROME1, RGB等.

Tag Value含义
MONOCHROME1Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as white after any VOI gray scale transformations have been performed. See PS3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. May be used for pixel data in a Native (uncompressed) or Encapsulated (compressed) format; see Section 8.2 in PS3.5
MONOCHROME2Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as black after any VOI gray scale transformations have been performed. See PS3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. May be used for pixel data in a Native (uncompressed) or Encapsulated (compressed) format; see Section 8.2 in PS3.5 .
RGBPixel data represent a color image described by red, green, and blue image planes. The minimum sample value for each color plane represents minimum intensity of the color. This value may be used only when Samples per Pixel (0028,0002) has a value of 3. Planar Configuration (0028,0006) may be 0 or 1. May be used for pixel data in a Native (uncompressed) or Encapsulated (compressed) format; see Section 8.2 in PS3.5 .

由于这里主要说的是DR图像.因此主要比较: Photometric Interpretation是: MONOCHROME1和MONOCHROME2的区别.

对于绝大部分CT和DR/CR/DX图像,它们都是黑色区域,表示密度较低的区域.也就是它们的Photometric Interpretation的值是:
MONOCHROME2.

但对于一些DR的机器,或乳腺的机器,经常会出现: MONOCHROME1的图像.

之前我还以为这样的图像,是拍摄的时候,机器出现了故障,才出现的数据.然后需要我们来校正一下.
但后来通过询问GPT, 才了解到,这其实可能是故意为之的.

在这里插入图片描述
在这里插入图片描述

GPT给出的回答是:对于某一些传统的显示设备,或专家,他们更习惯来看,就是用白色代表密度低,黑色代表密度高的片子. 因此,在拍摄的时候,设备才会这样而为之.

既然了解了这样拍摄的原因.但是公司在进行模型训练的时候,还仅是拿着MONOCHROME2的数据进行标注和训练.因此,为了能够适配模型,还是需要将MONOCHROME1的图像, 调整为MONOCHROME2的图像.

那么大体思路,就是找出整张图像中的最大像素值,然后用最大像素值,减去当前的像素值,得到的差值,就是反色后的像素值.然后,就可以修改它的Photometric Interpretation为MONOCHROME2.

2. 解决方案:

根据以上提供的解题思路, 可以写一个简单的函数, 来将反片图像, 校正为正片图像.

2.1 第一次反色的效果:

import pydicom
import numpy as np

def reverse_pixel(file_path, out_file):
    img_dataset = pydicom.dcmread(file_path)
    if img_dataset.PhotometricInterpretation != "MONOCHROME2":
        img_dataset.PhotometricInterpretation = "MONOCHROME2"
        pixel_array_transformed = np.array(img_dataset.pixel_array)
        max_pixel = np.max(pixel_array_transformed)
        pixel_mid1_array = pixel_array_transformed.copy()
        pixel_mid1_array[:] = max_pixel
        # 使用整个pixel_array里面的灰度最大值, 减去对应像素点的灰度值, 将差值赋予回原来的像素点, 即得到了反色后的图像.
        pixel_new_array = np.subtract(pixel_mid1_array, pixel_array_transformed)

        img_dataset.PixelData = pixel_new_array.tobytes()

        img_dataset.save_as(out_file)
 

根据以上的函数, 输入一张反片的图像,经过处理后, 预期是应该得到正片图像. 但实际得到的, 用软件查看, 是一张黑图.

输入图像:
在这里插入图片描述

处理后的图像变成了:
在这里插入图片描述
看到这个结果, 第一反应有点懵. 不知道是什么原因.
查看了反色后的图像, 它的pixel_array, 也都是正常的. 原来的像素最高的像素点, 灰度值变成了最小值, 其他的像素点, 灰度值也都发生了翻转.

后来, 我也不知道是什么原因, 就索性调整了一下, dicom viewer软件下面的窗宽窗位的滑块.
这时, 随着窗位(WindowLevel)不断调整, 原来黑色的图像, 慢慢地就显示出了, 反色校正后的图像, 就像变魔术一样.
这个时候, 我才恍然大悟.

在进行反色校正后, 还有一步必须要做的工作, 就是需要将它的窗位也相应进行一个翻转.
在这里插入图片描述
以上是, 在同一个窗宽窗位下面, 左侧是反色图, 右侧是校正后的图的表现.
由于图像的拍摄后的窗宽窗位, 是为了原来的反片, 能够正常展示的.

那么, 在图像整体的灰度值都发生了翻转后, 如果还沿用原来的窗宽窗位, 肯定是没办法显示正常的.
最重要的是窗位WindowCenter, 它决定了整个窗宽的上限和下限, 也就决定了, 这个图像的灰度可见范围.

因为小于下限的灰度值, 都会是黑色;大于上限的灰度值, 都会是白色. 只有在窗宽范围内的图像, 才是可以看出灰阶变化的.

于是, 基于这个发现, 在原来的反色代码上, 增加一个窗位的调整, 即可实现反色后的图像, 默认可以正常展示的目的.
在这里插入图片描述
根据上面的示意图:
大概的原理就是:
1, 由于图像整个像素的灰度都发生了翻转. 比如原来的ROI(感兴趣区域)的灰度值, 正好和当前的WindowLevel/Center = 3755是一致的, 所以可以在反片中, 看到ROI区域;
2, 经过反片校正后, ROI区域的灰度值, 从原来的3755, 变成了4096 - 3755 = 340.
如果维持当前的窗宽窗位不变, 只能展现: 3441 ~ 4069这个灰度范围内的图像, 而ROI区域的灰度值是340, 小于这个下限, 所以小于3441的区域, 都会被置为黑色.
这就解释了, 为什么第一次反片校正后, 整个图像都是黑色的了.
3, 将WindowLevel/Center从原来的3755, 调整为4095 - 3755 = 340, 那么能够显示影像的灰度范围, 就变成了 26 ~ 654的灰度区域.
而ROI的灰度值为340, 正好落在了这个灰度范围内, 所以就可以看到了.

经过调整后的函数为:

import pydicom
import numpy as np

def reverse_pixel(file_path, out_file):
    img_dataset = pydicom.dcmread(file_path)
    if img_dataset.PhotometricInterpretation != "MONOCHROME2":
        img_dataset.PhotometricInterpretation = "MONOCHROME2"
        pixel_array_transformed = np.array(img_dataset.pixel_array)
        max_pixel = np.max(pixel_array_transformed)
        pixel_mid1_array = pixel_array_transformed.copy()
        pixel_mid1_array[:] = max_pixel
        # 使用整个pixel_array里面的灰度最大值, 减去对应像素点的灰度值, 将差值赋予回原来的像素点, 即得到了反色后的图像.
        pixel_new_array = np.subtract(pixel_mid1_array, pixel_array_transformed)

        img_dataset.PixelData = pixel_new_array.tobytes()

		# 首先读取图像原始的窗位信息, 然后用最大的灰度值,减去之前的WindowCenter,赋予反色校正后的图像,作为新的WindowCenter.
		origin_window_center = img_dataset.WindowCenter
		img_dataset.WindowCenter = max_pixel - origin_window_center

        img_dataset.save_as(out_file)
 

以上是增加了, 修改窗位后的, 反色前后的图像对比.
可以看到, 两幅图像的窗位发生了变化. 反片是3755, 正片是340.

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inter_peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值