zoukankan      html  css  js  c++  java
  • 图像处理之细胞计数器

    很久以前写的一段代码。医学院某个实验室有一系列电子显微镜拍摄的细胞照片,他们需要人工统计每张图片里细胞的数目,对比前后照片来分析药物对组织产生的影响。人工计数的工作量太庞大了,于是他们找我们实验室合作。

    这个问题本质上就是一个图像分割的问题,把照片中的每个细胞分割开,然后求一下连通域的个数就好。

    % input image ---> tophat/bottomhat filter ---> image enhancement--->binarization by a histogram based threshold
    %  ---> calculate seed points ---> segmentation or plot edges of blobs ---> count connected components

    整个流程比较简单,图像预处理,调整亮度和对比度,区域分割,然后是连通域处理。用Matlab实现的,代码全都贴在这里了。这是实验阶段,后来又用OpenCVS和Qt写了一个简单的包含图形界面的程序给他们使用,如果有需要的同学可以邮件联系。

    function [outputImage, number_of_nuclei] = nuclei_counter(sourceImage, threshold)
    % This script accept an input nuclei image taken under microscope,
    % then preprocess the image with tophat and bottomhat filter, enhance its 
    % contrast by multiplying gamma. Convert it to binary image with a histogram 
    % based threshold, count the number of connected components and detect edges
    % of nucleus with LoG filter, then plot edges. Or calculate distance transform 
    % and detect seed points,use watershed algorithm for segmentation.
    % 
    % flow chart:
    % input image ---> tophat/bottomhat filter ---> image enhancement--->binarization by a histogram based threshold
    %  ---> calculate seed points ---> segmentation or plot edges of blobs ---> count connected components
    %  
    % refrence:
    % * Yousef Al-Kofahi, et al. Improved Automatic Detection and Segmentation of Cell Nuclei in Histopathology Images. 
    %   IEEE TRANSACTIONS ON BIOMEDICAL ENGINEERING, VOL. 57, NO. 4, APRIL 2010
    % * Jos B.T.M, et al, The Watershed Transform: Defnitions, Algorithms and Parallelization Strategies
    %   Fundamenta Informaticae 41 (2001) 187{228
    % 
    % Input
    %     sourceImage: 8 bits grayscale image;
    %     threshold: threshold [0 1] for binarization.
    %     
    % Output:
    %     outputImage: source image with overlayed contour
    %     number_of_nuclei: number of nucleis in image
    %     
    % If you have any ideas or improvements about this method, welcome to contact me 'zhyh8341@gmail.com'.
    
    
    % display original image
    image = sourceImage;
    figure;imshow(image);
    title('input image');
    
    total = numel(image);
    
    
    % apply top hat and bottom hat filter
    se = strel('disk',30);
    tophat = imtophat(image,se);
    bottomhat = imbothat(image,se);
    filterImage = image + (tophat - bottomhat);
    se = strel('disk',15);
    tophat = imtophat(filterImage,se);
    bottomhat = imbothat(filterImage,se);
    filterImage = filterImage + (tophat - bottomhat);
    
    % calculate histogram of filtered image
    % estimate more than 78.5% area is background (pi/4 = .785)
    [counts,x] = imhist(filterImage);
    ssum = cumsum(counts);
    bg = .215*total;
    fg = .99*total;
    low = find(ssum>bg, 1, 'first');
    high = find(ssum>fg, 1, 'first');
    adjustedImage = imadjust(filterImage, [low/255 high/255],[0 1],1.8);
    
    
    % image binarization, threshold is choosen based on experience
    if(nargin < 2)
        matrix = reshape(adjustedImage,total,1);
        matrix = sort(matrix);
        threshold = graythresh(matrix(total*.5:end));
    end
    binarization = im2bw(adjustedImage,threshold);
    
    
    % open image and then detect edge using laplacian of gaussian
    se2 = strel('disk',5);
    afterOpening = imopen(binarization,se2);
    nsize = 5; sigma = 3;
    h = fspecial('log',nsize,sigma);
    afterLoG = uint8(imfilter(double(afterOpening)*255,h,'same').*(sigma^2)); 
    
    
    se2 = strel('disk',5);
    afterOpening = imopen(binarization,se2);
    number_of_nuclei = bwconncomp(afterOpening);
    
    
    % % you can either use watershed method to do segmentation
    % D = -bwdist(~afterOpening);
    % D(~afterOpening) = -Inf;
    % L = watershed(D);
    
    
    outputImage = sourceImage + afterLoG*5;
    figure;imshow(outputImage);
    title('output image');

    一个简单的例子:

    % this is just an example to show how to use this function
    
    % read an image
    I = imread('img01.JPG');
    
    % convert it to grayscale of just take one channel
    % Igray = rgb2gray(I);
    Iblue = I(:,:,3);
    
    % call the nuclei counter function
    [outputImage, number_of_nuclei] = nuclei_counter(Iblue);

    效果如下:

  • 相关阅读:
    天真的误会
    Unity3D笔记
    http纪要
    JQuery中ajax错误处理之页面跳转
    php代码片段
    3D游戏相关笔记
    Javascript笔记
    PHP对观察者模式的支持
    为什么要使用多线程
    死锁和活锁
  • 原文地址:https://www.cnblogs.com/naive/p/4216791.html
Copyright © 2011-2022 走看看