如何以编程方式实时执行图像分割

时间:2015-02-26 11:29:38

标签: opencv image-processing computer-vision image-segmentation

我目前正在尝试分割血管(视频帧)的超声图像,例如直接在下面的图像。

在饱和通道上使用简单的二进制滤波器(下面的代码),我可以得到一个不令人满意的结果,如下面的第3张图片。当然,我尝试使用OpenCV Imgproc.dilate()将过滤后的区域扩大几个像素,但问题在于它增加了将过滤区域与相邻黑色区域连接很多的机会,从而导致不可接受的精度损失在随后的计算中。

如果有这种分割经验的人会非常友好地指出我有一个很好的技术来实现接近下面第二张图像的实时(30帧/秒),那真是太棒了! / p>


如何分割此基本图像:

base image

所以看起来更像是手绘分割:

human segmented image

虽然饱和通道上的简单二进制滤波器不是那么好:

saturation-filtered image

我的饱和过滤功能(java):

public static Mat threshold_onsat (Mat frame, Mat hsv_frame, int saturation){
    double sat = (double) saturation;
    List<Mat> lhsv = new ArrayList<Mat>(3);
    Mat masked = new Mat();
    Core.split(hsv_frame, lhsv);
    Mat sat_mask = lhsv.get(1);
    Imgproc.threshold(sat_mask, sat_mask, sat, 255D, Imgproc.THRESH_BINARY_INV);
    frame.copyTo(masked, sat_mask);
    return masked;
}

3 个答案:

答案 0 :(得分:1)

我想你可能想看一个叫做活动形状的更复杂的方法。虽然我不是医学图像处理的专家,但我知道我的一位朋友已经成功地使用这种方法来分割腹部动脉瘤(ouch)的内外表面,这似乎与您的应用松散相关。您可以找到有关in this paper主题的更多信息。

答案 1 :(得分:1)

我认为您可以坚持使用当前的饱和度过滤器,因为它可以识别您的区域。但是然后使用形态学操作来增强它。我会使用侵蚀,然后扩张。 (不只是你尝试过的扩张)。侵蚀步骤消除了噪音,然后扩张使面罩变大。我实际上连续做了两次扩张,以创造一个更漂亮的面具。 enter image description here

我在matlab中做了一个快速测试,作为概念证明。我只使用matlab,因为测试非常快(约5分钟),但我知道openCV具有非常相似的功能(扩张/侵蚀元素,imerode,imdilate)。阅读代码注释,有一些关于该过程的好信息。代码本身并不重要,仅供参考。更重要的部分是了解它的作用。我试图将我的“面具”与你的面具相匹配,而我根本没有使用你的轮廓区域。

segmented_im = rgb2gray(imread('binary_saturation_image.png'));
segmented_im = segmented_im(3:end,:);
orig_im = rgb2gray(imread('base_image.png'));

%i recreated your mask here, it looked like your mask had 0 values so thats
%what i used. it's 1 in region of interest and 0 elsewhere, this is
%important to take note of
mask = (segmented_im==0);

%creates a structuing element for our morphological operators, Another way
%to thing of this is like a nearest neighbor operation. This structuring
%element defines what your neighbors are, we are using a disk with radius 7
% in openCV this is your erosion/dilation element, the closest would be MORPH_ELLIPSE
%but using different elements and sizes may you get a better shape
%also using different shapes for the erosion vs dilation may help you
%further shape your mask
se = strel('disk',7,0);

%now we erode the image (this expands the 0 regions) we do this to remove
%noise, those small little dots around the mask
mask_erode = imerode(mask,se);

%now we dilate the image (expands the 1 regions) this will give us a more
%rounded mask
mask_dilate1 = imdilate(mask_erode,se);

%we do it one more time to round out the shape more
mask_dilate2 = imdilate(mask_dilate1,se);

%now we invert the mask (so the areas of interest are 0, and 1 elsewhere)
invert_mask = uint8(~mask_dilate2);

%we multiply the original image by our mask (so the area of interest has
%zero values)
newly_segmented = orig_im .* invert_mask;


figure()
subplot(2,3,1);imshow(orig_im);title('base image');
subplot(2,3,2);imshow(mask);title('mask');
subplot(2,3,3);imshow(mask_erode);title('mask erode image');
subplot(2,3,4);imshow(mask_dilate1);title('mask dilate1 image');
subplot(2,3,5);imshow(mask_dilate2);title('mask dilate2 image');
subplot(2,3,6);imshow(newly_segmented);title('newly segmented image');

答案 2 :(得分:0)

由于有人将这个问题添加到他的收藏中,我会发布我最好的主管:

可用于此类问题的最佳解决方案似乎确实是主动轮廓分割,我从洛桑工业学院的生物医学成像组找到了this Esnake implementation。它是一个ImageJ插件,但我希望能够将它实现到我自己的应用程序中。