MATLAB image processing experiment - segmentation and counting of cell images

1. Experiment content

This experiment is a cell image segmentation and counting system written in MATLAB, which realizes the counting of cells in the image, and the measurement of the perimeter and area of ​​each cell, and displays the image of each cell after segmentation.

The experimental steps are divided into image preprocessing, image pre-segmentation, cavity filling, adhesion cell segmentation, cell number statistics, cell feature statistics and display.

The images used in the experiment are shown in the following figure:


2. Image preprocessing

Use filtering to perform edge-preserving and denoising processing on cell images. The main function of this step is to remove image noise. The system provides median filtering, mean filtering, Wiener filtering, and sharpening filtering. After testing, the effect of median filtering was found. It is best, so take median filtering as an example to conduct the following experiments.

Part of the code is as follows:

global original_img show_img;
str=get(hObject,'string');
axes(handles.axes1);
[m,n,k]=size(original_img);
switch str
    case 'original image'
        show_img=original_img;
        imshow(show_img);
    case 'median filter'  
        show_img=original_img;
        for i=1:3
            show_img(:,:,i)=medfilt2(show_img(:,:,i));
        end
        imshow(show_img);
    case 'mean filter'
        show_img=original_img;
        h=ones(3,3)/9;
        for i=1:3
            show_img(:,:,i)=imfilter(show_img(:,:,i),h);
        end
        imshow(show_img);
    case 'Wiener filter'
        show_img=original_img;
        for i=1:3
            show_img(:,:,i)=wiener2(show_img(:,:,i),[5 5]);
        end
        imshow(show_img);
    case 'sharpening filter'
        show_img=original_img;
        h=[0 1 0;1 -4 1;0 1 0];
        for i=1:3
            J=conv2(im2double(show_img(:,:,i)),h,'same');
            show_img(:,:,i)=show_img(:,:,i)-uint8(J);
        end
        imshow(show_img);  
end

The median filtered image is as follows:


3. Pre-segmentation

Select the blue channel of the color cell image, and use the Otsu method to perform binarization pre-segmentation on the grayscale image of this channel, and segment the cells as the foreground.

global show_img;
B=show_img(:,:,3);
B_gray=im2double(B);
level=graythresh(B_gray);
B_bw=im2bw(B_gray,level);
axes(handles.axes1);
show_img=B_bw;
imshow(show_img);

The pre-segmented images are as follows:


4. Hole filling

The open operation is performed on the segmented binary image to fill the holes in the cells, so that the slightly adherent cells are separated and the small cells disappear.

global show_img;
se = shot ('disk', 5);
Spot_filled=imopen(show_img,se);
axes(handles.axes1);
show_img=Spot_filled;
imshow(show_img);

The image after filling the hole is as follows:


5. Adherent cell segmentation

Use watershed segmentation to segment the cells with severe adhesion in the image. For cells that are still difficult to be separated, use manual segmentation, use the mouse as a pen, set the value of the drawn pixel to 0, and then release the mouse. A watershed segmentation.

Watershed segmentation code:

global show_img;
D=-bwdist(~show_img);
mask=imextendedmin(D,2);
D2=imimposemin(D,mask);
Ld=watershed(D2);
Water_splited=show_img;
Water_splited(Ld==0)=0;
axes(handles.axes1);
show_img=Water_splited;
imshow(show_img);
Manually split the code:

global ButtonDown  show_img;  
if ButtonDown == 1  
    pos = get(handles.axes1, 'CurrentPoint');
    row=floor(pos(1,2));
    col=floor(pos(1,1));
    Diy_splited=show_img;
    Diy_splited(row,col)=0;
    show_img=Diy_splited;
    axes(handles.axes1);
    imshow(show_img);
end  

The segmented image is as follows:


6. Cell number statistics and display

First, delete the cells on the edge, then use the four-connected region labeling algorithm to count the number of non-adherent cells after segmentation, and finally mark and label the segmented cells on the original image.

Code for counting the number of cells:

global N show_img original_img img_group perimeter_group area_group;
[B,L,N]=bwboundaries(show_img,'noholes');
[m,n]=size(show_img);
counted_img=zeros(m,n);
for i=1:N
    % show edges
    for j=1:size(B{i},1)
        counted_img(B{i}(j,1),B{i}(j,2))=1;
    end
    % sign
    med_row=floor(mean(B{i}(:,1)));
    med_col=floor(mean(B{i}(:,2)));
    if floor(i/10)==0
        str=[num2str(i) '.png'];
        I=imread(str);
    else
        str1=[num2str(floor(i/10)) '.png'];
        str2=[num2str(rem(i,10)) '.png'];
        I1=imread(str1);
        I2=imread(str2);
        I=[I1 I2];
    end
    [number_row,number_col]=size(I);
    counted_img((med_row - (number_row/2)):(med_row + (number_row/2) - 1),(med_col - (number_col/2)):(med_col + (number_col/2) - 1))=I;
    % Take an image of each cell
    item_img = original_img (med_row - 45: med_row + 44, med_col - 45: med_col + 44, :);
    item_img_index = L (med_row - 45: med_row + 44, med_col - 45: med_col + 44);
    index=find(item_img_index~=i);
    r=item_img(:,:,1);
    g=item_img(:,:,2);
    b=item_img(:,:,3);
    r(index)=255;
    g(index)=255;
    b(index)=255;
    item_img=cat(3,r,g,b);
    img_group{i}=item_img;
    % perimeter per cell
    item_perimeter=size(B{i},1);
    perimeter_group{i}=item_perimeter;
    % area per cell
    item_area=length(find(L==i));
    area_group{i}=item_area;
end

Original image cell labeling code:

R=original_img(:,:,1)+uint8(counted_img*255);
G=original_img(:,:,2)+uint8(counted_img*255);
B=original_img(:,:,3)+uint8(counted_img*255);
show_img=cat(3,R,G,B);
axes(handles.axes1);
imshow(show_img);
The statistical results are as follows:

7. Statistics and display of cell characteristics

For each cell, count its area, extract the cell edge, count the number of pixels on the edge contour, that is, the cell perimeter, and display the image and related information of each cell separately.

global N img_group perimeter_group area_group page pages;
page=1;
pages=ceil(N/6);
str=['Number' num2str(page) '/' num2str(pages) 'page'];
set(handles.page_num,'string',str);
if page~=pages
    axes(handles.item1);imshow(img_group{1});
    axes(handles.item2);imshow(img_group{2});
    axes(handles.item3);imshow(img_group{3});
    axes(handles.item4);imshow(img_group{4});
    axes(handles.item5);imshow(img_group{5});
    axes(handles.item6);imshow(img_group{6});
    for i=1:6
        strs{i}=['No.' num2str(i) ' ' '周长:' num2str(perimeter_group{i}) ' ' '面积:' num2str(area_group{i})];
    end
    set(handles.detail_info1,'string',strs{1});
    set(handles.detail_info2,'string',strs{2});
    set(handles.detail_info3,'string',strs{3});
    set(handles.detail_info4,'string',strs{4});
    set(handles.detail_info5,'string',strs{5});
    set(handles.detail_info6,'string',strs{6});
else
    item_img=ones(size(img_group{1}));
    item_img(:,:,:)=255;
    item_imgs{1:6}=item_img;
    item_strs{1:6}='';
    for i=1:N
        item_imgs{i}=img_group{i};
        item_strs{i}=['No.' num2str(i) '   ' '周长:' num2str(perimeter_group{i}) '   ' '面积:' num2str(area_group{i})];
    end
    axes(handles.item1);imshow(item_imgs{1});
    axes(handles.item2);imshow(item_imgs{2});
    axes(handles.item3);imshow(item_imgs{3});
    axes(handles.item4);imshow(item_imgs{4});
    axes(handles.item5);imshow(item_imgs{5});
    axes(handles.item6);imshow(item_imgs{6});
    
    set(handles.detail_info1,'string',item_strs{1});
    set(handles.detail_info2,'string',item_strs{2});
    set(handles.detail_info3,'string',item_strs{3});
    set(handles.detail_info4,'string',item_strs{4});
    set(handles.detail_info5,'string',item_strs{5});
    set(handles.detail_info6,'string',item_strs{6});
end

The paging display results are as follows:


8. Experimental experience

This experiment took 3 days to complete, and all the functions required by the experiment were realized. However, due to the rush of time, there are still many details that need to be improved. During the experiment, some functions were difficult to implement in the code. Fortunately, a solution was finally found. The following are the three most difficult problems and detailed solutions that I think are encountered in the process of coding.

(1) Manual segmentation

After using watershed segmentation, there are still cells that have not been segmented, and manual segmentation is required. The method is to respond through the GUI mouse. When the mouse is pressed and moved, the horizontal and vertical coordinates of the pixel where the current cursor is located are obtained, the value at the corresponding position in the image is changed to 0, and a new image is displayed. During the mouse movement, the speed of modifying the image is much slower than the sliding speed of the mouse, which will only leave some black dots on the path that the mouse has drawn, instead of a line. When the mouse is released, a watershed segmentation is performed on the image again, and a segmentation line will be generated along the path of the black dot, thereby realizing the manual segmentation of severely adherent cells.

(2) The cell label of the original image

First, make an image of 10 numbers from 0 to 9 by drawing software, and use MATLAB to process the binary image of each number for subsequent labeling. After the image is marked by bwboundaries, the horizontal and vertical coordinates of the edge pixels of each cell are obtained, and then the center position coordinates of each cell are calculated. The coordinates correspond to the center coordinates of the corresponding digital image, and the digital image is added to On the original image, so as to realize the labeling of the original image cells. For cells whose labels are two-digit numbers, it is necessary to splicing the numbers on the tens and the numbers on each digit to generate a new image for labeling.

(3) Paging display of results

Since the operation of GUI objects cannot be realized through the loop structure, firstly, 6 all-white images are generated, and then the corresponding images are modified according to the number of cells to be displayed on this page, and finally all the 6 images are displayed. If it is a cell image, the cell image will be displayed, and if it is not a cell image, a completely white image will be displayed.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324730322&siteId=291194637