Detecting water level in an image I have designed a surface with a shape like a rounded rectangle and I want to detect its exact boundaries in a photo I take from it. A sample photo is like this:



I have tried thresholding the image but even after a Gaussian smoothing, the threshold won't give me an exact boundary.

Does anyone know of a technique that would give me the precise boundaries, regardless of the issues in lighting, etc?

UPDATE:
I'm sorry I didn't state the problem well, and actually I wasn't aware of the real problem (though I think it hasn't changed too much):

Here is the new photo. The photo is taken looking down inside a plastic bucket with a small amount of water inside, and I need to segment the region inside the water from the walls of the bucket, so I can detect the objects inside the water later. There is some lighting illuminating the bottom of the bucket from underneath (actually a sheet of plexiglass is placed instead of the original bottom).



The problem is that the reflections of light on the wall make it the same color as where the water is, in some areas like the bottom-center in the sample image which makes it hard to find the water level.

Also, I would appreciate any hints on how should I differentiate between the boundary related to the plexiglass, and the boundary related to the water level.

Thanks
Behold the power of shortest path.

The solution roughly follows what I did here: Detecting and isolating part of an image.

In this case we first treat the image by limiting every pixel value above the water-level grey to that same intensity.



Then performing shortest path on the inverse edge image created with a difference of Gaussian filter we get:



Resulting in the following segmentation:



My MATLAB functions that are needed for this solution:

http://imageprocessing.com.au/research/code/polarTransform.m http://imageprocessing.com.au/research/code/circularShortestPath.m http://imageprocessing.com.au/research/code/linearShortestPath.m

Code:

clear all
close all

%% Load image
I = imread('CabQx.jpg');
I = double(rgb2gray(I));
figure
imagesc(I);
colormap gray(256); 
title('Image');

%% Adjust intensity
Ia = I;
Ia(Ia &gt; 49) = 49;
figure
imagesc(Ia);
colormap gray(256); 
title('Adjusted Image');

%% Bandpass Kernel
H1 = fspecial('gaussian',[100,100],8); % *** Changed filter size
H2 = fspecial('gaussian',[100,100],2);  % *** 
H = H2-H1;
H = mat2gray(H);
figure;
imagesc(H);
colorbar;
colormap gray(256); 
title('Bandpass kernel');

%% Edge Kernel
Hedge = imag(hilbert(H));
figure;
imagesc(Hedge);
colormap gray(256); 
title('Edge Kernel');

%% Edge filtered image
G = sqrt(imfilter(Ia,Hedge,'replicate').^2 + imfilter(Ia,Hedge.','replicate').^2);
G = max(G(:)) - G;
imagesc(G);
colormap gray(256); 
title('Inverse edge filtered image');

%% Shortest path
% Mid point
[r,c] = size(G);
r = floor(r/2);
c = floor(c/2);
% Min radius and max radius
min_radius = 100;
max_radius = 1000;
% Shortest path
[ path, energy, lastIndex, pathImage ] = ...
    circularShortestPath(G, 100, [c,r], [min_radius,max_radius], [400,720*2]);
figure;
imagesc(I);
hold on;
plot(path(:,1),path(:,2),'r','LineWidth',2);
hold off;
colormap gray(256); 
title('Shortest path');

%% Segment
figure
imagesc(I);
hold on;
fill(path(:,1),path(:,2),'r');
hold off;
colormap gray(256); 
title('Mask')

%%
J = zeros(size(I));
mask = roipoly(J,path(:,1),path(:,2));
segmentedI = I .* mask;
figure;
imagesc(segmentedI);
colormap gray(256); 
title('Segmented image');