使用图像处理进行手部骨折检测 [英] Fracture detection in hand using image proccessing

查看:234
本文介绍了使用图像处理进行手部骨折检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了什么:


  1. 将输入图像和调整后的图像调整为标准尺寸

  1. Taken input image and resized image to standard size

因为我必须将它与模板进行比较。

as I have to compare it with template.

使用阈值转换为二进制。

converted in binary using threshold value.

检测到已连接的组件并显示最大的组件。

Detected connected component and displayed largest component.

因为它是整个hand.as显示在这里:

As it is whole hand.as shows here:

将图像放在相同的坐标处以检查手指的位置以便与模板图像进行比较

Place image at same coordinates to check placement of finger for comparison with template image

但是它们的位置不同紫色的是模板图像

but their positioning is different purple one is template image

我正在用图像减法进行图像比较。

I m doing comparison of image with Image subtraction method.

这些情况将会无法预测它们是否是发际线断裂,因为它们在图像中检测到许多小线。

These case will not able to predict if their is hairline fracture as their are many small lines detected in image.

是否是他们的任何其他做这些的方法?如果他们是他们的,请告诉我。

Is their any other method to do these? Let me know if their any.

此处原始未处理的图片:

Here original unprocessed images:


推荐答案

你几乎得到了它但是我的想法(来自评论)更像是这样:

You almost got it but what I had in mind (from comments) was more like this:


  1. 准备图片

切换到灰度,消除噪音(通过一些模糊),增强动态范围等。

switch to gray-scale, remove noise (by some bluring), enhance dynamic range, etc.

通过 x,y 轴来创建图像并创建渐变2D字段

derive image by both x,y axises and create gradient 2D field

所以重新着色图像并创建2D矢量场。每个像素都有RGB,因此对一个轴使用R而对另一个使用B.我这样做:

so recolor the image and create 2D vector field. each pixel has RGB so use R for one axis and B for the other. I do this like this:

Blue(x,y)=abs(Intensity(x,y)-Intensity(x-1,y))
Red (x,y)=abs(Intensity(x,y)-Intensity(x,y-1))

子结果如下所示:

用于强调边缘的阈值图像

因此选择每个像素并比较蓝色(x,y)+红色(x,y)< ; treshold 如果true重新着色为未知,则重新着色为边缘颜色。对于您的样本图像,我使用阈值 24 之后平滑结果以填充模糊颜色的小间隙。子结果如下所示:

So pick each pixel and compare Blue(x,y)+Red(x,y)<treshold if true recolor to unknown else recolor to edge color. For your sample image I used treshold 24 After that smooth the result to fill the small gaps with blurred color. The sub result looks like this:

绿色的东西是我的未知颜色和白色边缘。你可以看到我模糊了很多(懒得实现连接的组件)。

The greenish stuff is my unknown color and White are edges. As you can see I blurred quite a lot (too lazy to implement connected components).

检测背景

所以现在要区分背景和里面的骨头我使用特殊的填充方法(但是一个简单的填充就可以了)我开发了 DIP 的东西,发现非常有用很多超过以前预期的时间。

So now to distinguish background from the bones inside I use special filling method (but a simple flood fill will do) I developed for DIP stuff and found very useful many times over the former expectations.

void growfill(DWORD c0,DWORD c1,DWORD c2); // grow/flood fill c0 neigbouring c1 with c2

这只是检查图像中的所有像素,如果找到颜色 c0 c1 附近然后将其重新处理为 c2 并且循环,直到没有重新着色。由于不需要递归或堆栈/堆/列表,因此更大的分辨率通常比泛洪填充快得多。此外,它可以用于许多很酷的效果,如稀释/加厚等,只需几次调用。

Which simply checks all pixels in the image and if found color c0 near c1 then recolors it to c2 and loop until no recolor has occur. For bigger resolution is usually much faster then flood fill due to no need for recursion or stack/heap/lists. Also it can be use for many cool effects like thinning/thickening etc with simple few calls.

好的回到主题我选择3种基色:

OK back to the topic I choose 3 base colors:

                             //RRGGBB
const DWORD col_unknown   =0x00408020;  // yet undetermined pixels
const DWORD col_background=0x00000000;
const DWORD col_edge      =0x00FFFFFF;

现在背景是边缘肯定所以我用col_background绘制矩形图像和增长填充所有 col_unknown col_background 附近的像素,其中 col_background 基本上从外部填充图像在内部。

Now background is around edges for sure so I draw rectangle with col_background around image and growth fill all col_unknown pixels near col_background with col_background which basically flood fill image from outside to inside.

在此之后,我将所有不是3种定义颜色中的任何颜色的像素重新着色到最接近的匹配。这将消除模糊,因为它不再需要。子结果如下所示:

After this I recolor all pixels that are not any of the 3 defined colors to their closest match. This will remove the blur as it is not desirable anymore. The sub result looks like this:

细分/标记

现在只扫描整个图像,如果发现任何 col_unknown ,请用对象不同的颜色/索引填充它。更改实际对象的不同颜色/索引(增量)并继续直到图像结束。请注意你所拥有的颜色,以避免使用3种预定颜色,否则你会合并你不想要的区域。

Now just scan whole image and if any col_unknown is found growth fill it with object distinct color/index. Change the actual object distinct color/index (increment) and continue until end of image. Beware with the colors you have to avoid the use of the 3 predetermined colors otherwise you merge the areas which you do not want.

最终结果如下:

现在您可以应用任何形式的分析/比较

您获得了每个对象区域的像素掩码,因此您可以计算像素(区域)并删除忽略太小的区域。计算每个对象的平均像素位置(中心),并使用它来检测它实际上是哪个骨骼。计算区域的同质性...重新缩放到模板骨骼......等等...

you got pixel mask of each object region so you can count the pixels (area) and remove ignore too small areas. Compute the avg pixel position (center) of each object and use that to detect which bone it actually is. Compute the homogenity of area ... rescale to template bones ... etc ...

这里一些C ++代码我这样做

color c,d;
int x,y,i,i0,i1;
int tr0=Form1->sb_treshold0->Position;  // =24 treshold from scrollbar
                             //RRGGBB
const DWORD col_unknown   =0x00408020;  // yet undetermined pixels
const DWORD col_background=0x00000000;
const DWORD col_edge      =0x00FFFFFF;
// [prepare image]
pic1=pic0;                  // copy input image pic0 to output pic1
pic1.pixel_format(_pf_u);   // convert to grayscale intensity <0,765>
pic1.enhance_range();       // recompute colors so they cover full dynamic range
pic1.smooth(1);             // blur a bit to remove noise
// extract edges
pic1.deriveaxy();           // compute derivations (change in intensity in x and y axis as 2D gradient vector)
pic1.save("out0.png");
pic1.pf=_pf_rgba;           // from now on the recolored image will be RGBA (no need for conversion)
for (y=0;y<pic1.ys;y++)     // treshold recolor
 for (x=0;x<pic1.xs;x++)
    {
    c=pic1.p[y][x];
    i=c.dw[picture::_x]+c.dw[picture::_y];              // i=|dcolor/dx| + |dcolor/dy|
    if (i<tr0) c.dd=col_unknown; else c.dd=col_edge;    // treshold test&recolor
    pic1.p[y][x]=c;
    }
pic1.smooth(5);             // blur a bit to fill the small gaps
pic1.save("out1.png");

// [background]
// render backround color rectangle around image
pic1.bmp->Canvas->Pen->Color=rgb2bgr(col_background);
pic1.bmp->Canvas->Brush->Style=bsClear;
pic1.bmp->Canvas->Rectangle(0,0,pic1.xs,pic1.ys);
pic1.bmp->Canvas->Brush->Style=bsSolid;
// growth fill all col_unknonw pixels near col_background pixels with col_background similar to floodfill but without recursion and more usable.
pic1.growfill(col_unknown,col_background,col_background);
// recolor blured colors back to their closest match
for (y=0;y<pic1.ys;y++)
 for (x=0;x<pic1.xs;x++)
    {
    c=pic1.p[y][x];
    d.dd=col_edge      ; i=abs(c.db[0]-d.db[0])+abs(c.db[1]-d.db[1])+abs(c.db[2]-d.db[2]);             i0=i; i1=col_edge;
    d.dd=col_unknown   ; i=abs(c.db[0]-d.db[0])+abs(c.db[1]-d.db[1])+abs(c.db[2]-d.db[2]); if (i0>i) { i0=i; i1=d.dd; }
    d.dd=col_background; i=abs(c.db[0]-d.db[0])+abs(c.db[1]-d.db[1])+abs(c.db[2]-d.db[2]); if (i0>i) { i0=i; i1=d.dd; }
    pic1.p[y][x].dd=i1;
    }
pic1.save("out2.png");

// [segmentation/labeling]
i=0x00202020; // labeling color/idx
for (y=0;y<pic1.ys;y++)
 for (x=0;x<pic1.xs;x++)
  if (pic1.p[y][x].dd==col_unknown)
    {
    pic1.p[y][x].dd=i;
    pic1.growfill(col_unknown,i,i);
    i+=0x00050340;
    }
pic1.save("out3.png");

我使用自己的图片类图片,所以有些成员是:

I use my own picture class for images so some members are:


  • xs,ys 图片大小(以像素为单位)

  • p [y] [x] .dd (x,y)的像素位置为32位整数类型

  • p [y] [x] .dw [2] (x,y)的像素位置为 2D 字段的2x16位整数类型

  • p [y] [x] .db [4] (x,y)的像素位置为4x8位整数类型,便于频道访问

  • 清除(颜色) - 清除整个图像

  • 调整大小(xs,ys) - 调整图像大小新决议

  • bmp - VCL 封装 GDI 带Canvas访问权限的位图

  • smooth(n) - 快速模糊图像 n

  • growfill(DWORD c0,DWORD c1,DWORD c2) - grow / flood fill c0 neigbouring c1 ,带 c2

  • xs,ys size of image in pixels
  • p[y][x].dd is pixel at (x,y) position as 32 bit integer type
  • p[y][x].dw[2] is pixel at (x,y) position as 2x16 bit integer type for 2D fields
  • p[y][x].db[4] is pixel at (x,y) position as 4x8 bit integer type for easy channel access
  • clear(color) - clears entire image
  • resize(xs,ys) - resizes image to new resolution
  • bmp - VCL encapsulated GDI Bitmap with Canvas access
  • smooth(n) - fast blur the image n times
  • growfill(DWORD c0,DWORD c1,DWORD c2) - grow/flood fill c0 neigbouring c1 with c2

[Edit1]基于扫描线的骨骼检测

在链接的查找范围QA中,您必须投射扫描线并搜索识别骨骼的不同特征。我将从图像的部分推导开始(在x轴上),如下所示::

As in the linked find horizon QA you have to cast scan lines and search for distinct feature recognizing a bone. I would start with the partial derivation of image (in x axis) like this one::

左边是x的颜色强度推导(灰色表示零)和右边的原始图像。侧面图是作为 x y 的函数的推导图,用于实际鼠标位置的行和行。正如您所看到的,每个骨骼在推导中具有可以检测到的独特形状。我使用了一个非常简单的探测器:

On the left is the color intensity derivation by x (gray means zero) and on the right original image. The side graphs are the derivation graphs as a function of x and y taken for line and row of actual mouse position. As you can see each bone has a distinct shape in the derivation which can be detected. I used a very simple detector like this:


  1. 对于已处理的图像行,通过 x

  2. 查找所有峰值(圆圈)

  3. 删除太小的峰值并将相同的符号峰值合并在一起

  4. 通过其4个后续峰值检测骨骼:

  1. for processed image line do a partial derivation by x
  2. find all peaks (the circles)
  3. remove too small peaks and merge the same sign peaks together
  4. detect bone by its 4 consequent peaks:

  1. 大阴性

  2. 小阳性

  3. 小负面

  4. 大正

  1. big negative
  2. small positive
  3. small negative
  4. big positive


对于每个找到的骨骼边缘,我在原始图像中(在大峰的位置)渲染红色和蓝色像素,以便在视觉上检查正确性。您也可以在y轴上以相同的方式执行此操作并合并结果。为了改善这一点,您应该使用更好的检测,例如通过使用相关... ...

For each found bone edge I render red and blue pixel in the original image (on place of the big peaks) to visually check correctness. You van do this also in y axis in the same manner and merge the results. To improve this you should use better detection for example by use of correlation ...

而不是边缘渲染您可以轻松创建骨骼的蒙版然后将其细分为单独的骨骼和句柄,如上文所示。你也可以使用形态学操作来填补任何空白。

Instead of the edge rendering You can easily create a mask of bones and then segmentate it to separate bones and handle as in the above text. Also you can use morphological operations to fill any gaps.

我能想到的最后一件事就是为骨骼的关节侧添加一些检测(形状在那里不同)。它需要大量的实验,但至少你知道要走哪条路。

The last thing I can think of is to add also some detection for the joints side of bones (the shape is there different). It needs a lot of experimenting but at least you know which way to go.

这篇关于使用图像处理进行手部骨折检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆