Search code examples
imagematlabimage-processingedge-detectionnoise-reduction

How to detect a particular contour in a MATLAB plot?


I'm trying to extract a particular outline from a MATLAB pcolor plot (generated from a matrix named M which is uploaded here as well) as shown in this image:

Original Plot
Fig. Original Plot

However I would like to extract the contour only, as shown here:

Required Plot
Fig. Required Plot

The yellow color line is the one which I would like to extract and is highlighted here for illustration purpose.

But I'm getting the result as the following:

Obtained Plot
Fig. Obtained Plot

I don't require any other bits/clutter apart from the curve.

I'm applying the following code on the matrix M to obtain the erroneous result.

[~, threshold] = edge(M, 'sobel');
fudgeFactor = 0.6;
BWs = edge(M,'sobel', threshold * fudgeFactor);
se90 = strel('line',6,70);
se0 = strel('line',3,90);
BWsdil = imdilate(BWs, [se90 se0]);
BWnobord = imclearborder(BWsdil,18);
seD = strel('cube',3);
BWfinal = imerode(BWnobord,seD);
BWfinal = imerode(BWfinal,seD);
pcolor(BWfinal);colormap(jet);   shading interp;   colorbar;

How to only obtain the contour as required? Do I have to use any edge detection filters or do I have to perform smoothing prior to applying any filters?

UPDATE: I applied a guassian filter and obtained the following image. The noise in the upper portions still exist. I want only the curve to be extracted. Image after applying a Gaussian filter

sigma = 30;
smoothImage = imgaussfilt(M,sigma);
smoothGradient = imgradient(smoothImage,'CentralDifference');
pcolor(smoothGradient);colormap(jet);   shading interp;   colorbar;

Solution

  • You could do something like this, although this is not really mathematically sound and is sort of hard coded for the particular matrix you have provided..

    clear; close all; clc;
    load('Matrix M.mat');
    
    M(181:182,:)=0; % some noise (?) you can skip this line, it will still work..
    M(M>0)=1; % binary
    
    % smoothing
    sigma = 10;
    gauss_submatrix = imgaussfilt(M, sigma); 
    
    % thresholding
    threshold = 0.05;
    gauss_submatrix(gauss_submatrix<threshold) = 0; 
    gauss_submatrix(gauss_submatrix>=threshold) = 1; 
    
    % getting the boundary
    a = cumsum(gauss_submatrix);
    [rows, cols] = find(a==1);
    
    figure;
    hold on;
    imagesc(M(1:450,:));
    line(cols, rows);
    hold off;
    ylim([0 450]);
    xlim([0 size(M, 2)]);
    

    You could play with the sigma and the threshold to get the boundary closer to what you actually desire.

    enter image description here