how to segment sky & water part in a picture - matlab

I'm trying to segment the sky and water part in this image.
Link of the Picture
I've tried so many methods like k-means, threshold, multi threshold etc. BUt unfortunately nothing worked so well.
Here is an example of my code(Matlab):
img=imread('1.jpg');
im_gray=rgb2gray(img);
b=imadjust(im_gray);
imshow(b);
bw_remove_small=imopen(b,strel('square',5));
imshow(bw_remove_small); %after 1st iteration
m3=medfilt2(bw_remove_small,[18,16]);
imshow(m3);
m3=medfilt2(bw_remove_small,20,20]);
m3=medfilt2(bw_remove_small,[20,20]);
imshow(m3);
I1=m3;
I2=rgb2gray(I1);
I=double(I2);
figure
subplot(1,3,1)
imshow(I1)
subplot(1,3,2)
imshow(I2)
g=kmeans(I(:),4);
J = reshape(g,size(I));
subplot(1,3,3)
imshow(J,[]);
Can any one help me?please

The picture's two regions are different in hue, texture, and gray level brightness.
The horizon is the best line in the image from our point of view and can be seen by the distinct change in brightness. The brightness will not work with a single threshold because the image brightness is not flat, so use brightness a model of the distribution to flatten out the sky or the water. This implies knowledge of the objective but there are two things that can give you an approximate answer: texture and/or hue.
The hue with a threshold of 120 (derived from the hue histogram) will give you the two regions but will not be divided cleanly and will have overlapping sections. Though using these two sections a model of the brightness can be found.
The same with texture. Using a small fft of the image, subtracting the dc out, then averaging or just summing up the non dc parts will result in a histogram with two peaks that may not be as distinct as the hue's is but is enough to find a threshold and two areas that will allow a model of the brightness to be found.
The key fact is if the sky is modeled properly as a gray surface then you can subtract it out of the image and use a simple threshold to pull it out.
Edge detection is very noisy in this image to be able to easily see the line but if you can pull out the image lines without losing shape then look for a straight and long contour it may take less code/work.
Hope this helps some! I used this to find mountains in the distance when there was not a big difference between the sky and the mountains. Plus I just tried this on your pic and almost got a good answer without a good model of the sky.

Related

Histogram after thresholding

I have an image and I apply thresholding to it to apply binary mask.I draw histogram before and after the thresholding process.The histograms look like below.
The second figure which is after thresholding,doesn't show any peaks.Is that mean,my thresholding is wrong.Can anyone please explain these histograms.
Update
Image after thresholding
To summarize Sardar's comment, the horizontal range of your plot is tight. Simply loosen the range a bit so you can see the result better. Doing xlim([-0.5 1.5]); will certainly do that and we can see that in the last figure of your update. How you interpret the histogram... well, for black and white images, examining the histogram is never meaningful because there are only two possible intensities to examine - 0 and 1. Histograms usually give a glimpse as to the contrast of the image. If the histogram is spread out, this usually gives an indication that the image has high contrast. However, if the histogram is within a small range this usually means the image is poor contrast.
Remember that the histogram simply count the occurrence of instances in a data set. In this case, we are counting how many times we see 0 and 1 in the image. Referring to your last plot, this means that approximately 9000 pixels that are intensity 0 and approximately 4000 pixels that are intensity 1. This gives absolutely no indication as to the contrast or the spread of the intensities in your image. because there are only two possible intensities that are seen in the image. As such, to answer your question in such a long-winded way, the answer is that you can't really interpret anything.
The only thing I can possible suggest is that it tells you the ratio of object pixels to background pixels and could indicate a measure of quality. Usually when we determine what is an object and what are background pixels, we would expect that there would be more background pixels than object pixels to be able to discern this from the background. Therefore, the more black pixels you have the better it may be. That being said, I can't really say more unless you actually show us what your image looks like after you threshold it.

Image Processing Q: Separate/segment an image

need some help here on image processing. I'm using Matlab and try to segment the following figure based on the two major peaks (in yellow). The color yellow means higher value and blue means low value (on z-axis, or image color from 0 to 1 for your convenience). The ideal cut is roughly the line from point (1,75) to (120,105). But I want a systematic way to derive this rather than by observation.
My intuition was to first identify the two peaks (based on this), and then classify each point/pixel on this figure to the two peaks (the metric here is to compute the shortest Euclidean distance to the edge of the two peaks).
And I end up with the following fig.
As you can see, the cut is pretty much a straight line, which I'm not quite satisfied. Maybe I can use the orientation of the peak circle and somehow tilt the line.. but I'm not sure how to do so? Any clues? Thanks.
This is an Image segmentation problem.
you can use GMM Gaussian of Mixture Model to model the image.
in your case the number of components will be 2.
after you model the image by using this mixture, you can find the probability of each pixel P(pixel x belong to the first component or the second component)
check
http://www.mathworks.com/matlabcentral/newsreader/view_thread/272162
http://www.mathworks.com/help/stats/cluster-data-from-mixture-of-gaussian-distributions.html

matlab: remove small edges and simplify an histology image

I have an image like this:
What I want to do is to find the outer edge of this cell and the inner edge in the cell between the two parts of different colors.
But this image contains to much detail I think, and is there any way to simplify this image, remove those small edges and find the edges I want?
I have tried the edge function provided by matlab. But it can only find the outer edge and disturbed by those detailed edges.
This is a very challenging work due to the ambiguous boundaries and tiny difference between red and green intensities. If you want to implement the segmentation very precisely and meet some medical requirements, Shai's k-means plus graph cuts may be one of the very few options (EM algorithm may be an alternative). If you have a large database that has many similar images, some machine learning methods might help. Otherwise, I just wrote a very simple code to roughly extract the internal red region for you. The boundary is not that accurate since some of the green regions are also included.
I1=I;
I=rgb2hsv(I);
I=I(:,:,1); % the channel with relatively large margin between green and red
I=I.*(I<0.25);
I=imdilate(I, true(5));
% I=imfill(I,'holes'); depends on what is your definition of the inner boundary
bw=bwconncomp(I);
ar=bw.PixelIdxList;
% find the largest labeled area,
n=0;
for i=1:length(ar)
if length(ar{i})>n
n=length(ar{i});
num=i;
end
end
bw1=bwlabel(I);
bwfinal(:,:,1)=(bw1==num).*double(I1(:,:,1));
bwfinal(:,:,2)=(bw1==num).*double(I1(:,:,2));
bwfinal(:,:,3)=(bw1==num).*double(I1(:,:,3));
bwfinal=uint8(bwfinal);
imshow(bwfinal)
It seems to me you have three dominant colors in the image:
1. blue-ish background (but also present inside cell as "noise")
2. grenn-ish one part of cell
3. red-ish - second part of cell
If these three colors are distinct enough, you may try and segment the image using k-means and Graph cuts.
First stage - use k-means to associate each pixels with one of three dominant colors. Apply k-means to the colors of the image (each pixel is a 3-vector in your chosen color space). Run k-means with k=3, keep for each pixel its distance to centroids.
Second stage - separate cell from background. Do a binary segmentation using graph-cut. The data cost for each pixel is either the distance to the background color (if pixel is labeled "background"), or the minimal distance to the other two colors (if pixel is labeled "foreground"). Use image contrast to set the pair-wise weights for the smoothness term.
Third stage - separate the two parts of the cell. Again do a binary segmentation using graph-cut but this time work only on pixels marked as "cell" in the previous stage. The data term for pixels that the k-means assigned to background but are labeled as cell should be zero for all labels (these are the "noise" pixels inside the cell).
You may find my matlab wrapper for graph-cuts useful for this task.

How to remove camera noises in CMOS camera

Here with i have attached two consecutive frames captured by a cmos camera with IR Filter.The object checker board was stationary at the time of capturing images.But the difference between two images are nearly 31000 pixels.This could be affect my result.can u tell me What kind of noise is this?How can i remove it.please suggest me any algorithms or any function possible to remove those noises.
Thank you.Sorry for my poor English.
Image1 : [1]: http://i45.tinypic.com/2wptqxl.jpg
Image2: [2]: http://i45.tinypic.com/v8knjn.jpg
That noise appears to result from camera sensor (Bayer to RGB conversion). There's the checkerboard pattern still left.
Also lossy jpg contributes a lot to the process. You should first have an access to raw images.
From those particular images I'd first try to use edge detection filters (Sobel Horizontal and Vertical) to make a mask that selects between some median/local histogram equalization for the flat areas and to apply some checker board reducing filter to the edges. The point is that probably no single filter is able to do good for both jpeg ringing artifacts and to the jagged edges. Then the real question is: what other kind of images should be processed?
From the comments: if corner points are to be made exact, then the solution more likely is to search for features (corner points with subpixel resolution) and make a mapping from one set of points to the other images set of corners, and search for the best affine transformation matrix that converts these sets to each other. With this matrix one can then perform resampling of the other image.
One can fortunately estimate motion vectors with subpixel resolution without brute force searching all possible subpixel locations: when calculating a matched filter, one gets local maximums for potential candidates of exact matches. But this is not all there is. One can try to calculate a more precise approximation of the peak location by studying the matched filter outputs in the nearby pixels. For exact match the output should be symmetric. Otherwise the 'energies' of the matched filter are biased towards the second best location. (A 2nd degree polynomial fit + finding maximum can work.)
Looking closely at these images, I must agree with #Aki Suihkonen.
In my view, the main noise comes from the jpeg compression, that causes sharp edges to "ring". I'd try a "de-speckle" type of filter on the images, and see if this makes a difference. Some info that can help you implement this can be found in this link.
In a more quick and dirty fashion, you apply one of the many standard tools, for example, given the images are a and b:
(i) just smooth the image with a Gaussian filter, this can reduce noise differences between the images by an order of magnitude. For example:
h=fspecial('gaussian',15,2);
a=conv2(a,h,'same');
b=conv2(b,h,'same');
(ii) Reduce Noise By Adaptive Filtering
a = wiener2(a,[5 5]);
b = wiener2(b,[5 5]);
(iii) Adjust ntensity Values Using Histogram Equalization
a = histeq(a);
b = histeq(b);
(iv) Adjust Intensity Values to a Specified Range
a = imadjust(a,[0 0.2],[0.5 1]);
b = imadjust(b,[0 0.2],[0.5 1]);
If your images are supposed to be black and white but you have captured them in gray scale there could be difference due to noise.
You can convert the images to black and white by defining a threshold, any pixel with a value less than that threshold should be assigned 0 and anything larger than that threshold should be assigned 1, or whatever your gray scale range is (maybe 255).
Assume your image is I, to make it black and white assuming your gray scale image level is from 0 to 255, assume you choose a threshold of 100:
ind = find(I < 100);
I(ind) = 0;
ind = find(I >= 100);
I(ind) = 255;
Now you have a black and white image, do the same thing for the other image and you should get very small difference if the camera and the subject have note moved.

Segmenting 3D shapes out of thick "lines"

I am looking for a method that looks for shapes in 3D image in matlab. I don't have a real 3D sample image right now; in fact, my 3D image is actually a set of quantized 2D images.
The figure below is what I am trying to accomplish:
Although the example figure above is a 2D image, please understand that I am trying to do this in 3D. The input shape has these "tentacles", and I have to look for irregular shapes among them. The size of the tentacle from one point to another can change around but at "consistent and smooth" pace - that is it can be big at first, then gradually smaller later. But if suddenly, the shape just gets bigger not so gradually, like the red bottom right area in the figure above, then this is one of the volume of interests. Note that these shapes have more tendency to be rounded and spherical, but some of them are completely arbitrary and random.
I've tried the following methods so far:
Erode n times and dilate n times: given that the "tentacles" are always smaller than the volume of interest, this method will work as long as the volume is not too small. And, we need to have a mechanism to deal with thicker portion of the tentacle that becomes false positive somehow.
Hough Transform: although I have been suggested this method earlier (from Segmenting circle-like shapes out of Binary Image), I see that it works for some of the more rounded shape cases, but at the same time, more difficult cases such that of less-rounded, distorted, and/or arbitrary shapes can slip through this method.
Isosurface: because of my input is a set of 2D quantized images, using an isosurface allow me to reconstruct image in 3D and see things clearer. However, I'm not sure what could be done further in this case.
So can anyone suggests some other techniques for segmenting such shape out of these "tentacles"?
Every point on your image has the property that it is either part of the tentacle, or part of the volume of interest. If it is unknown apriori what the expected girth of the tentacle is, then 1 wont work because we won't be able to set n. However, we know that the n that erases the tentacle is smaller than the n that erases the node. You can for each point replace it with an integer representing the distance to the edge. Effectively, this can be done via successive single pixel erosion, and replacing each pixel with the count of the iteration at which it was erased. Lets call this the thickness at the pixel, but my rusty old mind tells me that there was a term of art for this.
Now we want to search for regions that have a higher-than-typical morphological distance from the boundary. I would do this by first skeletonizing the image (http://www.mathworks.com/help/toolbox/images/ref/bwmorph.html) and then searching for local maxima of the thickness along the skeleton. These are points on the skeleton where the thickness is larger than the neighbor points.
Finally I would sort the local maxima by the thickness, a threshold on which should help to separate the volumes of interest from the false positives.