10

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.

Community
  • 1
  • 1
Honeybear
  • 2,296
  • 1
  • 20
  • 37
  • It is not very efficient, but you could chose height 1 to 0 with some step, e.g. 0.1, then for each height you calculate the number of peaks. If a new peak is encountered the first time you save its height, if 2 peaks become connected then they are either two peaks (both high enough, take area at middle height), or one peak (only one high enough, fuse and continue) or one potential peak (none of them high enough yet, fuse peaks and continue, taking the higher point as new mountain top for the "free standing mountain height" calculation). – maraca May 08 '17 at 23:31
  • The H-minima transform is often used together with with watershed. It removes local minima with less "depth" than the parameter h. There are equivalen algorithms that remove mínima associated with volumes smaller than a certain value. I think this is what you're looking for. – Cris Luengo May 09 '17 at 01:41
  • @maraca: You inspired me to work on a variant based on this idea. I think this is leads to a refined watershed algorithm: threshold from top to bottom (like filling up the inverse landscape) and marking newly found peaks (like inverse basins). Plain watershed wouldn't merge peaks (basins), so the merging is the refinement. You suggest using "area middle height" as merge criteria. Applying h-minima filter to the watershed input would be like varying the stepsize or using a "minimum height" merge criteria. I'm thinking of using a combined merge criteria, but won't be able to implement this soon. – Honeybear May 09 '17 at 11:10
  • @CrisLuengo: Do you know implementations/papers regarding those algorithms that remove minima with small volumes? I didn't find anything so far. The H-minima approach I've tried (results can be seen above), but it isn't flexible enough if both high and low peaks are present (too high `h` parameter will mask peaks, too low will still result in oversegmentation as seen above). – Honeybear May 09 '17 at 11:16
  • I've seen this mentioned in various places, for example here: https://arxiv.org/pdf/1202.0216.pdf . But I don't know of any implementations. – Cris Luengo May 09 '17 at 18:37

1 Answers1

3

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

Ozcan
  • 684
  • 4
  • 12
  • Wow thank you, that actually generalizes pretty well to most of the other examples I have. I've worked with some morphological filters before, but didn't have the [tophat-filter](https://de.mathworks.com/help/images/ref/imtophat.html) and [extended-maxima-filters](https://de.mathworks.com/help/images/ref/imextendedmax.html) in my repertoire. – Honeybear May 10 '17 at 17:05