views:

396

answers:

4

Consider a black and white image like this http://img13.imageshack.us/img13/7401/10416827.jpg

alt text

What I am trying to do is to find the region where the white points are most dense. In this case there are 20-21 such dense regions. (i.e the clusters of points makes a dense region)

Can anyone give me any hint on how this can be achieved ?

+3  A: 

Maybe a naive approach:

You define a square of n*n which is the maximum size of the region in which you measure the density. For each point in the image you consider the point as the center of the square and count around the number of black (b) and white (w) points. Using the difference b-w you can determine in which square(s) is the most white.

The most dense regions must be determined in a fuzzy way. If one region has 600 white points and another 599 then, for the human eye, they are the same density. 600 is 100% dense while 599 is 99% dense and 1% non-dense. Use an epsilon for this.

n can be predefined or based on some function (ie. percent of image size).

You could also use a circle/ellipse instead of square/rectangle. Choose what fits your needs best

Victor Hurdugaci
+4  A: 

Sliding Window (simple but slow)

You could create a sliding window (e.g. 10x10 pixels size) which iterates over the image, and for each position you count the number of white pixels in this 10x10 field, and store the positions with the highest counts.

This whole process is O(n*m) where n is the number of pixels of the image, and m the size of the sliding window.

In other words, you convolve the image with a mean filter (here the box filter), and then use the extrema.

Sliding Window (fast)

At first, calculate a summed area table, which can be done very efficiently in a single pass:

  1. create a 2D array sat with the same size as the original image img.
  2. Iterate over each index, and calculate for each index x and y

    sat[x, y] = img[x, y] + sat[x-1, y] + sat[x, y-1] - sat[x-1, y-1]
    

    For example, given an image where 0 is dark and 1 is white, this is the result:

       img            sat
    0 0 0 1 0 0   0 0 0 1 1 1 
    0 0 0 1 0 0   0 0 0 2 2 2
    0 1 1 1 0 0   0 1 2 5 5 5
    0 1 0 0 0 0   0 2 3 6 6 6
    0 0 0 0 0 0   0 2 3 6 6 6
    
  3. Now iterate over the summed area table's indices with a sliding window, and calculate the number of white pixels in it by using the corners A, B, C, D of the sliding window:

       img            sat          window
    0 0 0 1 0 0   0 0 0 1 1 1   0 A-----B 1 
    0 0 0 1 0 0   0 0 0 2 2 2   0 | 0 2 | 2
    0 1 1 1 0 0   0 1 2 5 5 5   0 | 2 5 | 5
    0 1 0 0 0 0   0 2 3 6 6 6   0 | 3 6 | 6
    0 0 0 0 0 0   0 2 3 6 6 6   0 D-----C 6
    

    Calculate

    density(x', y') = sat(A) + sat(C) - sat(B) - sat(D)
    

    Which in the above example is

    density(1, 0) = 0 + 6 - 1 - 2 = 3
    

This process requires a temporary image, but it is just O(n), so speed is independent of the sliding window's size.

martinus
+6  A: 

if you have the image processing toolbox, blur it with a gaussian filter, then find the peaks/extrema.

vary the size of the gaussian filter to get the number of 'dense' regions you want.

Alex Cohen
+12  A: 

If you have access to the Image Processing Toolbox, you can take advantage of a number of filtering and morphological operations it contains. Here's one way you could approach your problem, using the functions IMFILTER, IMCLOSE, and IMREGIONALMAX:

%# Load and plot the image data:
imageData = imread('lattice_pic.jpg');  %# Load the lattice image
subplot(221);
imshow(imageData);
title('Original image');

%# Gaussian-filter the image:
gaussFilter = fspecial('gaussian',[31 31],9);  %# Create the filter
filteredData = imfilter(imageData,gaussFilter);
subplot(222);
imshow(filteredData);
title('Gaussian-filtered image');

%# Perform a morphological close operation:
closeElement = strel('disk',31);  %# Create a disk-shaped structuring element
closedData = imclose(filteredData,closeElement);
subplot(223);
imshow(closedData);
title('Closed image');

%# Find the regions where local maxima occur:
maxImage = imregionalmax(closedData);
maxImage = imdilate(maxImage,strel('disk',5));  %# Dilate the points to see
                                                %# them better on the plot
subplot(224);
imshow(maxImage);
title('Maxima locations');

And here's the image the above code creates:

alt text

To get things to look good I just kept trying a few different combinations for the parameters for the Gaussian filter (created using FSPECIAL) and the structuring element (created using STREL). However, that little bit of trial and error gave a very nice result.

NOTE: The image returned from IMREGIONALMAX doesn't always have just single pixels set to 1 (to indicate a maxima). The output image often contains clusters of pixels because neighboring pixels in the input image can have equal values, and are therefore both counted as maxima. In the code above I also dilated these points with IMDILATE just to make them easier to see in the image, which makes an even bigger cluster of pixels centered on the maxima. If you want to reduce the cluster of pixels to a single pixel, you should remove the dilation step and modify the image in other ways (add noise to the result or filter it, then find the new maxima, etc.).

gnovice
Why do you need the close filter step? It just closes dark holes. If you're only interested in the maxima, why would you want to that?
nikie
@nikie: As you can see from the bottom left plot above, the close step fills over both the dark holes as well as the smaller maxima. It essentially creates a series of flat, uniform "plateaus" around the largest maxima. If you look at the center of the filtered image, you can see one of those smaller maximas that is smoothed over by the close operation.
gnovice
@gnovice: What do you mean by "fills over"? It can't make the maxima areas smaller. It might connect a local maximum with a nearby bright area (so it's not a maximum any more), is that what you mean? (The plot is to small to tell.) Then you could have achieved the same effect by dilating the gauss-filtered image and selecting the pixels that have equal brightness in the dilated and the gauss-filtered image, right? (i.e. the pixels that are at least as bright as the brightest pixel in a certain neighborhood).
nikie
@nikie: There are likely a number of ways to approach this problem. I chose IMCLOSE because I was simply looking for different ways to "flatten" regions between the largest maxima. IMCLOSE uses a dilation followed by an erosion, so it expands the largest maxima out over smaller ones, then shrinks them back. Your solution (dilation plus comparison with the filtered image) would certainly be feasible, but you would likely have to use a larger structuring element to make sure all the non-maxima pixels get dilated over, and one "true" maxima may inadvertently dilate over another in this case.
gnovice