Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find peak (regions) in 2D data

I am looking to find peak regions in 2D data (if you will, grayscale images or 2D landscapes, created through a Hough transform). By peak region I mean a locally maximal peak, yet NOT a single point but a part of the surrounding contributing region that goes with it. I know, this is a vague definition, but maybe the word mountain or the images below will give you an intuition of what I mean.

The peaks marked in red (1-4) are what I want, the ones in pink (5-6) examples for the "grey zone", where it would be okay if those smaller peaks are not found but also okay if they are.

an optimal result in 3D

Images contain between 1-20 peaked regions, different in height. The 2D data for above surf plot is shown below with a possible result (orange corresponds to Peak 1, green corresponds to Peak 2 a/b, ...). Single images for tests can be found in the description links:

Image left: input image - - - - middle: (okaish) result - - - - right: result overlayed over image.

input, result and overlayed result

The result above was produced using simple thresholding (MATLAB code):

% thresh_scale = 15;                     % parameter: how many thresholding steps 
% thresh_perc = 6;                       % parameter: threshold at which we clip
thresh = multithresh(H,thresh_scale);    
q_image = imquantize(H, thresh);         

q_image(q_image <= thresh_perc) = 0;     % regions under threshold are thrown away
q_image(q_image > thresh_perc) = 1;      % ... while all others are preserved
q_image = imbinarize(q_image);           % binarize for further processing
B = bwareaopen(q_image, nhood_minsize);  % Filter really small regions
[L, L_num] = bwlabel(B); % <- result     % Label connected components

Some values like these (15 and 6) often work fine if there are few similar peaks, but this isn't consistent if more peaks are present or they vary a lot. I mainly have two problems, that also can't be fixed by simply adjusting the parameters:

  • higher peaks can mask lower (but clearly distinguishable) peaks. Since the threshold is relative to the highest peak, other peaks may fall below.
  • in some cases the valley between two peaks is above the threshold, merging several peaks into one (as can be observed with Peak 2 a/b).

I also don't want a huge region for a high peak, so the peak region should probably be defined as some percentage of the mountain. I figured instead of a global thresholding, I'd rather have a method that finds peak regions relative to their immediate environment. I've looked into mean-shift and MSER segmentation, but those seem to be suited for segmenting real images, not kind of synthetic data.

Somehow I imagined filling a negative of the landscape with a certain amount of water would give me the regions I'm looking for: basins that fill and spread with how the surrounding regions are shaped. Like pouring water over below image and the resulting waterpools are the regions I'm looking for.

negative image (complement), ready to pour water into it

I thought that is what the floodfill or watershed algorithm do, but floodfill seems like something completely else and the watershed results are not at all what I had in mind, also when applying some preprocessing that I thought could help (clipped at 1/10):

watershed clipped with threshold 1/10

Or when using the same clipping threshold as with above example (clipped at 6/15):

watershed clipped with threshold 6/15

Produced with this code (MATLAB):

thresh = multithresh(H, 10);    % set to either 10 || 15 for the examples
q_image = imquantize(H, thresh);
mask = false(size(q_image));    % create clipping mask...
mask(q_image > 1) = true;       % ... to remove lowest 10% || lowest 6/15
                                % show with: figure, imshow(mask);

% OPTIONAL: Gaussian smoothing
H = imgaussfilt(H, 2);  % apply before adding Inf values
% OPTIONAL: H-minima transform
H = imhmin(H, 10);      % parameter is threshold for suppressing shallow minima
H = -H;                 % Complement the image
H(~mask) = Inf;         % force "ground" pixels to Inf

L = watershed(D);    
L(~mask) = 0;                               % clip "ground" from result
imshow(label2rgb(L,'lines',[.5 .5 .5]));    % show result

My question now: Is there an algorithm that fills a landscape and gives me the resulting waterpools (for various amounts of water poured) to do what I've tried to achieve with above methods? Or any other suggestion is welcome. I'm implementing MATLAB (or if need be Python), but I can work with any code or pseude-code.

To distinguish this from this question, my maxima are not separated by zero-values. What I want is similar, yet none of the suggestions there are helpful (hill-climbing/simulated annealing will give you only one point...).

This question is also interesting, but it solves the problem with constraints (assume exactly 5 peaks of a certain size) that make the suggested approaches not useful for my case.

like image 996
Honeybear Avatar asked May 08 '17 16:05

Honeybear


1 Answers

In such peak finding problems, I mostly use morphological operations. Since the Hough transform results are mostly noisy, I prefer blurring it first, then apply tophat and extended maxima transform. Then for each local maximum, find the region around it with adaptive thresholding. Here is a sample code:

im=imread('udIuy.png');

% blur
im=imgaussfilt(im,1);

% tophat transform
im2=imtophat(im,strel('disk',5));

% extended maximums
im3=imextendedmax(im2,10);

% Extract each blob
s=regionprops(im3,'Centroid','PixelIdxList');

figure,imagesc(im),axis image

for i=1:numel(s)
    x=ceil(s(i).Centroid);
    tmp=im*0;
    tmp(s(i).PixelIdxList)=1;
    tmp2=tmp.*im2;

% The maximum amplitude and location

    [refV,b]=max(tmp2(:));
    [x2,y2]=ind2sub(size(im),b);

% select the region around local max amplitude    
    tmp=bwselect(im2>refV*0.6,y2,x2,4);  

    [xi,yi]=find(tmp);
    hold on, plot(yi,xi,'r.')
    hold on, text(y2+10,x2,num2str(i),'Color','white','FontSize',16)    
end

enter image description here

like image 65
Ozcan Avatar answered Oct 12 '22 20:10

Ozcan