删除dicom图像中的像素注释

问题描述 投票:3回答:7

我正在分析医学图像。所有图像都有一个带位置的标记。它看起来像这个enter image description here

它是此图像中的“TRH RMLO”注释,但在其他图像中可能有所不同。尺寸也各不相同。图像被裁剪,但您看到组织正在右侧开始。我发现这些标记的存在会扭曲我的分析。

我该如何删除它们?

我像这样在python中加载图像

import dicom
import numpy as np

img = dicom.read_file(my_image.dcm)
img_array = img.pixel_array

然后图像是一个numpy数组。白色文本总是被大的黑色区域包围(黑色值为零)。标记在每个图像中处于不同的位置。

如何在不伤害组织数据的情况下删除白色文本。

UPDATE

添加了第二张图片

enter image description here

UPDATE2:这是两个原始的dicom文件。所有个人信息均已删除。编辑:已删除

python image numpy image-processing dicom
7个回答
4
投票

查看您提供的图像的实际像素值,您可以看到标记几乎是(99.99%)纯白色,这不会出现在图像的其他位置,因此您可以使用简单的99.99%阈值将其隔离。

我更喜欢命令行中的ImageMagick,所以我会这样做:

convert sample.dcm -threshold 99.99% -negate mask.png

enter image description here

convert sample.dcm mask.png -compose darken -composite result.jpg

enter image description here

当然,如果样本图像不具代表性,您可能需要更加努力。我们来看看......

如果简单的阈值对你的图像不起作用,我会看“命中和错过形态学”。基本上,您将图像阈值设置为纯黑色和白色 - 大约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

enter image description here

希望你现在可以看到划分徽标角落的点,所以我们可以让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

enter image description here

如果你想要一个脚本自动执行,我会使用这样的东西,保存为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

1
投票

如果这些注释在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 );

如果将这些真正刻录到图像数据中,您可能会在此处使用其他建议之一。


1
投票

我有另一个想法。这个解决方案是使用python在OpenCV中。这是一个相当的解决方案。

  1. 首先,获得图像的二进制阈值。 ret,th = cv2.threshold(img,2,255, 0) enter image description here
  2. 进行形态膨胀:

dilate = cv2.morphologyEx(th, cv2.MORPH_DILATE, kernel, 3) enter image description here

  1. 为了加入差距,我使用了中值过滤:

median = cv2.medianBlur(dilate, 9) enter image description here

现在,您可以使用轮廓属性来消除最小轮廓并保留包含图像的另一个轮廓。

它也适用于第二个图像:

enter image description here


0
投票

好处是,这些水印可能是完全黑色的,这使得它更容易(尽管如果根据指定的用法删除它是有问题的;许可证的东西)。

没有专家,这是一个想法。它可能是针对此问题量身定制的一种非常强大的方法的草图,但您必须确定实现复杂性和算法复杂性(非常依赖于图像统计)是否值得:

Basic idea

  • 像边界一样检测半十字(4)
  • 从这些中计算定义的矩形
  • 遮挡此矩形

Steps

0

二值化

1

  • 使用一些基于梯度的边缘检测器来获得所有水平边缘
  • 可能有多个;您可以尝试给出最小长度(可能需要一些形态来连接基于源或算法中的噪声而未连接的像素)

2

  • 使用一些基于梯度的边缘检测器来获得所有水平边缘
  • 像上面一样,但是方向不同

3

  • 进行一些连通分量计算以获得一些垂直和水平线的对象
  • 现在,您可以使用以下知识尝试不同的候选组件选择(8个实际组件) 其中两个组件可以用同一条线描述(斜率截距形式;线性回归问题) - >与矩形相邻的线 最好的4对选择(根据线性回归损失)可能是这个矩形的有效边界 您可以添加假设,即垂直边框和水平边框彼此正交

4 - 从这些边框计算矩形 - 将其加宽几个像素(超参数) - 使矩形变黑

这是基本方法。

Alternative

这个工作少得多,使用更专业的工具并在开幕式中假设事实:

  • 要移除的东西是在图像的一些完全黑色的部分
  • 它有点孤立;与医疗数据的距离很高

脚步

  • 运行一些通用的OCR来检测字符
  • 以某种方式获取占用的像素/边框(我不确定OCR工具返回什么)
  • 计算一些外部矩形和黑屏(使用一些预定义的加宽间隙;这个需要比上面的大得多)

Alternative 2

仅限草图:想法是在图像上以某种方式使用像binary-closing这样的东西来构建源像素的完全连接组件(同时填充小间隙/孔),以便我们得到一个描述医疗数据的大组件和一个对于水印。然后删除较小的一个。


0
投票

标记在每个图像中处于不同的位置。

我的假设:

  1. 标记始终是文本。
  2. 标记不在组织内

=>建议:

  1. 使用OCR查找位置(例如,使用Tesseract在本地查找,或使用OCR.space等在线API)。您将获得以JSON形式返回的单词的边界框: "TextOverlay" : { "Lines" : [ { "Words": [ { "WordText": "RMLO", "Left": 106, "Top": 91, "Height": 9, "Width": 11 },
  2. 现在你有了坐标,你可以将矩形遮挡。

该解决方案与Sascha的第二个选项相对应。


0
投票

我确信这可以优化,但是......你可以创建4个大小为3x3或4x4的补丁,并使用注释文本周围框架的每个角落的像素值的确切内容对它们进行初始化。然后,您可以遍历整个图像(或者仅在黑色区域中进行一些智能初始化)并找到这些修补程序的完全匹配。在组织中你很可能不会有相同的规则结构(90度角被0附近包围),所以这可能会给你一个边界框。


0
投票

更简单的一个仍然可能!!!

只需实现以下(img_array = img.pixel_array)

img_array [img_array> X] = Y.

其中X是您希望在此之后消除的强度阈值。 Y也是您要考虑的强度值而不是它。

例如:img_array [img_array> 4000] = 0

用黑色强度0代替大于4000的白质。

© www.soinside.com 2019 - 2024. All rights reserved.