我正在分析医学图像。所有图像都有一个带位置的标记。它看起来像这个
它是此图像中的“TRH RMLO”注释,但在其他图像中可能有所不同。尺寸也各不相同。图像被裁剪,但您看到组织正在右侧开始。我发现这些标记的存在会扭曲我的分析。
我该如何删除它们?
我像这样在python中加载图像
import dicom
import numpy as np
img = dicom.read_file(my_image.dcm)
img_array = img.pixel_array
然后图像是一个numpy数组。白色文本总是被大的黑色区域包围(黑色值为零)。标记在每个图像中处于不同的位置。
如何在不伤害组织数据的情况下删除白色文本。
UPDATE
添加了第二张图片
UPDATE2:这是两个原始的dicom文件。所有个人信息均已删除。编辑:已删除
查看您提供的图像的实际像素值,您可以看到标记几乎是(99.99%)纯白色,这不会出现在图像的其他位置,因此您可以使用简单的99.99%阈值将其隔离。
我更喜欢命令行中的ImageMagick,所以我会这样做:
convert sample.dcm -threshold 99.99% -negate mask.png
convert sample.dcm mask.png -compose darken -composite result.jpg
当然,如果样本图像不具代表性,您可能需要更加努力。我们来看看......
如果简单的阈值对你的图像不起作用,我会看“命中和错过形态学”。基本上,您将图像阈值设置为纯黑色和白色 - 大约90%说,然后您查找特定形状,例如标签上的角标记。所以,如果我们想在黑色背景上寻找白色矩形的左上角,我们使用0
来表示“此像素必须为黑色”,1
表示“此像素必须为白色”而-
表示“我们不在乎”,我们会使用这种模式:
0 0 0 0 0
0 1 1 1 1
0 1 - - -
0 1 - - -
0 1 - - -
希望你能在那里看到一个白色矩形的左上角。在终端中就是这样的:
convert sample.dcm -threshold 90% \
-morphology HMT '5x5:0,0,0,0,0 0,1,1,1,1 0,1,-,-,- 0,1,-,-,- 0,1,-,-,-' result.png
现在我们还想查找右上角,左下角和右下角,因此我们需要旋转模式,当您添加>
标志时ImageMagick会轻松地执行此操作:
convert sample.dcm -threshold 90% \
-morphology HMT '5x5>:0,0,0,0,0 0,1,1,1,1 0,1,-,-,- 0,1,-,-,- 0,1,-,-,-' result.png
希望你现在可以看到划分徽标角落的点,所以我们可以让ImageMagick修剪所有无关黑色的图像,然后留下白点,然后告诉我们边界框:
cconvert sample.dcm -threshold 90% \
-morphology HMT '5x5>:0,0,0,0,0 0,1,1,1,1 0,1,-,-,- 0,1,-,-,- 0,1,-,-,-' -format %@ info:
308x198+1822+427
所以,如果我现在在这些坐标周围绘制一个红色框,你可以看到标签被检测到的位置 - 当然在实践中我会画一个黑盒子来覆盖它,但我在解释这个想法:
convert sample.dcm -fill "rgba(255,0,0,0.5)" -draw "rectangle 1822,427 2130,625" result.png
如果你想要一个脚本自动执行,我会使用这样的东西,保存为HideMarker
:
#!/bin/bash
input="$1"
output="$2"
# Find corners of overlaid marker using Hit and Miss Morphology, then get crop box
IFS="x+" read w h x1 y1 < <(convert "$input" -threshold 90% -morphology HMT '5x5>:0,0,0,0,0 0,1,1,1,1 0,1,-,-,- 0,1,-,-,- 0,1,-,-,-' -format %@ info:)
# Calculate bottom-right corner from top-left and dimensions
((x1=x1-1))
((y1=y1-1))
((x2=x1+w+1))
((y2=y1+h+1))
convert "$input" -fill black -draw "rectangle $x1,$y1 $x2,$y2" "$output"
然后你会这样做,使其可执行:
chmod +x HideMarker
并运行它:
./HideMarker someImage.dcm result.png
如果这些注释在DICOM文件中,则可以通过几种方式存储它们(请参阅https://stackoverflow.com/a/4857782/1901261)。只需从文件中删除60xx组属性即可清除当前支持的方法。
对于不推荐使用的方法(仍然常用),您可以手动清除未使用的高位注释,而不会弄乱其他图像数据。就像是:
int position = object.getInt( Tag.OverlayBitPosition, 0 );
if( position == 0 ) return;
int bit = 1 << position;
int[] pixels = object.getInts( Tag.PixelData );
int count = 0;
for( int pix : pixels )
{
int overlay = pix & bit;
pixels[ count++ ] = pix - overlay;
}
object.putInts( Tag.PixelData, VR.OW, pixels );
如果将这些真正刻录到图像数据中,您可能会在此处使用其他建议之一。
好处是,这些水印可能是完全黑色的,这使得它更容易(尽管如果根据指定的用法删除它是有问题的;许可证的东西)。
没有专家,这是一个想法。它可能是针对此问题量身定制的一种非常强大的方法的草图,但您必须确定实现复杂性和算法复杂性(非常依赖于图像统计)是否值得:
0
二值化
1
2
3
4 - 从这些边框计算矩形 - 将其加宽几个像素(超参数) - 使矩形变黑
这是基本方法。
这个工作少得多,使用更专业的工具并在开幕式中假设事实:
脚步
仅限草图:想法是在图像上以某种方式使用像binary-closing这样的东西来构建源像素的完全连接组件(同时填充小间隙/孔),以便我们得到一个描述医疗数据的大组件和一个对于水印。然后删除较小的一个。
标记在每个图像中处于不同的位置。
我的假设:
=>建议:
"TextOverlay" : {
"Lines" : [
{
"Words": [
{
"WordText": "RMLO",
"Left": 106,
"Top": 91,
"Height": 9,
"Width": 11
},
该解决方案与Sascha的第二个选项相对应。
我确信这可以优化,但是......你可以创建4个大小为3x3或4x4的补丁,并使用注释文本周围框架的每个角落的像素值的确切内容对它们进行初始化。然后,您可以遍历整个图像(或者仅在黑色区域中进行一些智能初始化)并找到这些修补程序的完全匹配。在组织中你很可能不会有相同的规则结构(90度角被0附近包围),所以这可能会给你一个边界框。
更简单的一个仍然可能!!!
只需实现以下(img_array = img.pixel_array)
img_array [img_array> X] = Y.
其中X是您希望在此之后消除的强度阈值。 Y也是您要考虑的强度值而不是它。
例如:img_array [img_array> 4000] = 0
用黑色强度0代替大于4000的白质。