Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image 如何有效地为这张显微图像创建BW遮罩?_Image_Matlab_Image Processing_Image Segmentation_Watershed - Fatal编程技术网

Image 如何有效地为这张显微图像创建BW遮罩?

Image 如何有效地为这张显微图像创建BW遮罩?,image,matlab,image-processing,image-segmentation,watershed,Image,Matlab,Image Processing,Image Segmentation,Watershed,所以有一些背景。我的任务是编写一个matlab程序来计算可见光显微镜图像中酵母细胞的数量。要做到这一点,我认为第一步将是细胞分割。在得到真实的实验图像集之前,我开发了一种算法,使用分水岭的测试图像集。看起来是这样的: 分水岭的第一步是为单元生成BW掩码。然后,我将生成一个bwdist图像,其中包含从BW掩码生成的强制局部最小值。有了它,我可以很容易地生成分水岭 正如您所见,我的算法依赖于BW掩码的成功生成。因为我需要从中生成bwdist图像和标记。最初,我按照以下步骤生成BW掩码: 生成图

所以有一些背景。我的任务是编写一个matlab程序来计算可见光显微镜图像中酵母细胞的数量。要做到这一点,我认为第一步将是细胞分割。在得到真实的实验图像集之前,我开发了一种算法,使用分水岭的测试图像集。看起来是这样的:

分水岭的第一步是为单元生成BW掩码。然后,我将生成一个bwdist图像,其中包含从BW掩码生成的强制局部最小值。有了它,我可以很容易地生成分水岭

正如您所见,我的算法依赖于BW掩码的成功生成。因为我需要从中生成bwdist图像和标记。最初,我按照以下步骤生成BW掩码:

  • 生成图像sdImage=stdfilt的局部标准偏差(灰度图像,1(9))
  • 使用BW阈值生成初始BW掩码binaryImage=sdImage<8

  • 使用imclearborder清除背景。使用其他代码将单元格添加到后边框上


    背景已完成。这是我的问题


    但今天我收到了新的真实数据集。图像分辨率小得多,光照条件与测试图像集不同。颜色深度也要小得多。这些使我的算法毫无用处。这是:

    使用stdfilt无法生成良好的干净图像。相反,它会生成如下内容(注意:我已经调整了stdfilt函数的参数和BW阈值,下面是我能得到的最佳结果):

    正如你所看到的,细胞中心有一些光像素,不一定比细胞膜暗。这导致bw阈值生成如下内容:

    bw阈值化后的新bw图像具有不完整的膜或分割的细胞中心,使其不适合其他步骤

    我最近才开始做图像处理,不知道该怎么做。如果你有主意,请帮帮我!谢谢


    为了您的方便,我附上了dropbox的链接,我认为您的方法存在一个根本问题。您的算法使用
    stdfilt
    对图像进行二值化。但这本质上意味着你假设在背景和细胞内有低“纹理”。这适用于您的第一张图像。但是,在第二张图像中,单元中有一个“纹理”,因此这一假设被打破

    我认为一个更有力的假设是,每个单元格周围都有一个“环”(对你发布的两张图片都有效)。所以我采取了探测这个戒指的方法

    因此,我的方法基本上是:

  • 检测这些环(我使用“log”过滤器,然后基于正值进行二值化。然而,这会导致很多“喋喋不休”
  • 尝试通过过滤掉非常小和非常大的区域来消除一些“抖动”
  • 现在,填充这些环。然而,细胞之间仍然有一些“颤振”和填充区域
  • 同样,删除大小区域,但由于单元格已填充,因此增加可接受范围
  • 还有一些不好的区域,大多数不好的区域将是细胞之间的区域。细胞之间的区域可以通过观察区域边界周围的曲率来检测。它们“向内弯曲”很多,在数学上表示为边界的大部分具有负曲率。此外,为了消除其余的“颤振”,这些区域的边界曲率将有一个大的标准偏差,因此也要去除具有大标准偏差的边界
  • 总的来说,最困难的部分将是在不移除实际单元的情况下移除单元之间的区域和“抖动”

    无论如何,这里是代码(注意,这里有很多启发法,而且非常粗糙,基于旧项目、家庭作业和stackoverflow答案的代码,所以肯定还远没有完成):

    cell=im2double(imread('cell1.png');
    if(大小(单元格,3)=3)
    单元=rgb2gray(单元);
    结束
    图(1),子批次(3,2,1)
    imshow(cell,[]);
    %检测边缘
    hw=5;
    cell_filt=imfilter(cell,fspecial('log',2*hw+1,1));
    子地块(3,2,2)
    imshow(cell_filt,[]);
    %首先移除硬件并过滤掉非单元硬件
    掩码=单元过滤器>0;
    hw=5;
    掩码=掩码(hw:end-hw-1,hw:end-hw-1);
    子地块(3,2,3)
    imshow(mask,[]);
    rp=区域属性(遮罩、“像素idxlist”、“区域”);
    rp=rp(垂直猫(相对面积)>50和垂直猫(相对面积)<2000);
    掩码(:)=假;
    掩码(vertcat(rp.PixelIdxList))=真;
    子地块(3,2,4)
    imshow(mask,[]);
    %现在填充对象
    mask1=真(尺寸(遮罩)+hw);
    mask1(hw+1:end,hw+1:end)=掩码;
    mask1=imfill(mask1,“孔”);
    mask1=mask1(hw+1:结束,hw+1:结束);
    mask2=真(尺寸(遮罩)+hw);
    mask2(hw+1:end,1:end hw)=掩码;
    mask2=imfill(mask2,“孔”);
    mask2=mask2(hw+1:end,1:end hw);
    mask3=真(大小(掩码)+hw);
    mask3(1:end-hw,1:end-hw)=掩码;
    mask3=imfill(mask3,“孔”);
    mask3=mask3(1:end hw,1:end hw);
    mask4=真(大小(掩码)+hw);
    mask4(1:end-hw,hw+1:end)=掩码;
    mask4=imfill(mask4,“孔”);
    mask4=mask4(1:end hw,hw+1:end);
    mask=mask1 | mask2 | mask3 | mask4;
    %再次过滤大区域和小区域
    rp=区域属性(遮罩、“像素idxlist”、“区域”);
    rp=rp(垂直猫(相对面积)>100和垂直猫(相对面积)<5000);
    掩码(:)=假;
    掩码(vertcat(rp.PixelIdxList))=真;
    子地块(3,2,5)
    imshow(mask);
    %过滤掉具有大量正凹度的区域
    %获得边界
    [B,L]=边界(掩码);
    %边界上的圈
    对于i=1:长度(B)
    b=b{i};
    %滤波器边界-使用循环卷积
    b(:,1)=cconv(b(:,1),f特殊('gaussian',[17],1'),大小(b,1));
    b(:,2)=cconv(b(:,2),f特殊('gaussian',[17],1'),大小(b,1));
    %求曲率
    曲线=零(尺寸b
    
    cell = im2double(imread('cell1.png'));
    if (size(cell,3) == 3) 
        cell = rgb2gray(cell);
    end
    
    figure(1), subplot(3,2,1)
    imshow(cell,[]);
    
    % Detect edges
    hw = 5;
    cell_filt = imfilter(cell, fspecial('log',2*hw+1,1));
    
    subplot(3,2,2)
    imshow(cell_filt,[]);
    
    % First remove hw and filter out noncell hws
    mask = cell_filt > 0;
    hw = 5;
    mask = mask(hw:end-hw-1,hw:end-hw-1);
    
    subplot(3,2,3)
    imshow(mask,[]);
    
    rp = regionprops(mask, 'PixelIdxList', 'Area');
    rp = rp(vertcat(rp.Area) > 50 & vertcat(rp.Area) < 2000);
    
    mask(:) = false;
    mask(vertcat(rp.PixelIdxList)) = true;
    
    subplot(3,2,4)
    imshow(mask,[]);
    
    % Now fill objects
    mask1 = true(size(mask) + hw);
    mask1(hw+1:end, hw+1:end) = mask;
    mask1 = imfill(mask1,'holes');
    mask1 = mask1(hw+1:end, hw+1:end);
    
    mask2 = true(size(mask) + hw);
    mask2(hw+1:end, 1:end-hw) = mask;
    mask2 = imfill(mask2,'holes');
    mask2 = mask2(hw+1:end, 1:end-hw);
    
    mask3 = true(size(mask) + hw);
    mask3(1:end-hw, 1:end-hw) = mask;
    mask3 = imfill(mask3,'holes');
    mask3 = mask3(1:end-hw, 1:end-hw);
    
    mask4 = true(size(mask) + hw);
    mask4(1:end-hw, hw+1:end) = mask;
    mask4 = imfill(mask4,'holes');
    mask4 = mask4(1:end-hw, hw+1:end);
    
    mask = mask1 | mask2 | mask3 | mask4;
    
    % Filter out large and small regions again
    rp = regionprops(mask, 'PixelIdxList', 'Area');
    rp = rp(vertcat(rp.Area) > 100 & vertcat(rp.Area) < 5000);
    
    mask(:) = false;
    mask(vertcat(rp.PixelIdxList)) = true;
    
    subplot(3,2,5)
    imshow(mask);
    
    % Filter out regions with lots of positive concavity
    
    % Get boundaries
    [B,L] = bwboundaries(mask);
    
    % Cycle over boundarys
    for i = 1:length(B)
        b = B{i};
    
        % Filter boundary - use circular convolution
        b(:,1) = cconv(b(:,1),fspecial('gaussian',[1 7],1)',size(b,1));
        b(:,2) = cconv(b(:,2),fspecial('gaussian',[1 7],1)',size(b,1));
    
        % Find curvature
        curv_vec = zeros(size(b,1),1);
        for j = 1:size(b,1)
            p_b = b(mod(j-2,size(b,1))+1,:);  % p_b = point before
            p_m = b(mod(j,size(b,1))+1,:);    % p_m = point middle
            p_a = b(mod(j+2,size(b,1))+1,:);  % p_a = point after
    
            dx_ds = p_a(1)-p_m(1);              % First derivative
            dy_ds = p_a(2)-p_m(2);              % First derivative
            ddx_ds = p_a(1)-2*p_m(1)+p_b(1);    % Second derivative
            ddy_ds = p_a(2)-2*p_m(2)+p_b(2);    % Second derivative
            curv_vec(j+1) = dx_ds*ddy_ds-dy_ds*ddx_ds;
        end
    
    
        if (sum(curv_vec > 0)/length(curv_vec) > 0.4 || std(curv_vec) > 2.0)
            L(L == i) = 0;
        end
    end
    
    mask = L ~= 0;
    
    subplot(3,2,6)
    imshow(mask,[])