Search code examples
matlabimage-processingshadowimage-segmentation

MATLAB- mices segmentation in grayscale images, which is invariant to shadows


After 2 or 3 days of search, I still didn't find a solution to my problem.

I want to create a segmentation of the mouse without the shadow. The problem is that If I manage to remove the shadow I also remove the tail and the feets which is a problem. The shadow comes from the wall of the arena in which the mouse is.

I want to remove the shadow from a grayscale image but I have no clue how doing it. First I removed the background of the image and I obtain the following picture.

enter image description here

edit1 : Thank you for the answer it works well when the shadow doesn't touch the mouse. This is what I get otherwise :

segmented mouse

from this original image :

original image

I am extracting each frame from a tif file and apply your code for each frame. This is the code I use :

for k=1:1000

    %reads image
    I = imread('souris3.tif',k);

    %first stage: perform thesholding and fill holes

    seg = I >20000;
    seg = imfill(seg,'holes');

    %fixes the missing tail problem
    %extract edges, and add them to the segmentation.
    edges =  edge(I);
    seg = seg | edges;

    %fill holes (again)
    seg = imfill(seg,'holes'); 

    %find all the connected components
    CC = bwconncomp(seg,8);

    %keeps only the biggest CC
    numPixels = cellfun(@numel,CC.PixelIdxList);
    [biggest,idx] = max(numPixels);
    seg = zeros(size(edges));
    seg(CC.PixelIdxList{idx}) = 1;

    imshow(seg);

end

I choose 20000 for step with the command impixelinfo because the image is in uint16 and it's the mean value of the mouse.

This is the link if you want to have the tif file :

souris3.tif

Thank you for helping.


Solution

  • I suggest the following approach:

    1. perform thresholding on the image, and get a mask which contains most of the mouse's body without his tail and legs.
    2. perform hole filling by using MATLAB's imfill function. At this stage, the segmentation is almost perfect, except for a part of the tail which is missing.
    3. use the edge map in order to find the boundaries of the tail. This can be done by adding the edges map to the segmentation and perform hole filling once again. keep only the biggest connected component at this stage.

    Code:

    %reads image
    I = rgb2gray(imread('mSWm4.png'));
    
    %defines thersholds (you may want to tweak these thresholds, or find
    %a way to calculate it automatically).
    FIRST_STAGE_THRESHOLD = 70;
    IM_BOUNDARY_RELEVANCE_THRESHOLD = 10;
    
    %perform thesholding and fill holes, the tail is still missing
    seg = I > FIRST_STAGE_THRESHOLD;
    seg = imfill(seg,'holes');
    
    %second stage fix the missing tail problem:
    %extract edges from relevant areas (in which the matter is not too dark), and add them to the segmentation.
    %the boundries of the image which are close enough to edges are also considered as edges
    edges =  edge(I);
    imageBoundries = ones(size(I));
    imageBoundries(2:end-1,2:end-1) = 0;
    relevantDistFromEdges = bwdist(edges) > IM_BOUNDARY_RELEVANCE_THRESHOLD;
    imageBoundries(bwdist(edges) > IM_BOUNDARY_RELEVANCE_THRESHOLD) = 0;
    seg = seg | (edges | imageBoundries);
    
    %fill holes (again) and perform noise cleaning
    seg = imfill(seg,'holes');
    seg = getBiggestCC(imopen(seg,strel('disk',1)));
    

    getBiggestCC function:

    function [ res ] = getBiggestCC(mask)
    CC = bwconncomp(mask,8);
    numPixels = cellfun(@numel,CC.PixelIdxList);
    [~,idx] = max(numPixels);
    res = zeros(size(mask));
    res(CC.PixelIdxList{idx}) = 1;
    end
    

    results

    results of each stage:

    enter image description here

    results image 1 results:

    enter image description here

    image 2 results:

    enter image description here

    Another view (segmentation is in red):

    enter image description here