Blobs detection using machine learning? - python

I have a large stack of images showing a bar with some dark blobs, whose position changes with time (see Figure, b). To detect the blobs I am now using an intensity threshold (c in Figure, where all intensity values below the threshold are set to 1) and then I search for blobs in the binary image using the Matlab code below. As you see the binary image is quite noisy, complicating the blobs detection process. Do you have any suggestion on how to improve the shape detection, maybe including some machine learning algorithm? Thanks!
Code:
se = strel('disk',1);
se_1 = strel('disk',3);
pw2 = imclose(IM,se);
pw3 = imopen(pw2,se_1);
pw4 = imfill(pw3, 'holes');
% Consider only the blobs with more than threshold pixels
[L,num] = bwlabel(pw4);
counts = sum(bsxfun(#eq,L(:),1:num));
number_valid_counts = length(find(counts>threshold));

This might help.
Extract texture features of the boundary of the blobs you want to extract. This can be done using Local binary patterns. There are many other texture features, you can get a detailed survey here.
Then use them to train a binary classifier.

It seems that the data come like pulses in the lower side of the image, I suggest to get some images and to slice vertical lines of the pixels perpendicular to the pulse direction, each time you take a line of values, little bit above and lower the pulse, the strip width is one pixel, and its height is little bit larger than the pulse image to take some of the light values lower and above the pulse, you may start from pixel 420-490, each time you save 70 grey values, those will form the feature vector, take also lines from the non blob areas to save for class 2, do this on several images and lines from each image.
now you get your training data, you may use any machine learning algorithm to train the computer for pulses and non pulses,
in the test step, you scan the image reading each time 70 pixels vertically and test them against the trained model, create a new black image if they belong to class "bolob" draw white vertical line starting from little below the tested pixel, else draw nothing on the output image.
at the end of scanning the image: check if there is an isolated white line you may delete considering it as false accepted . if you find a dark line within a group of white line, then convert it to white, considering false rejection.
you may use my classifier: https://www.researchgate.net/publication/265168466_Solving_the_Problem_of_the_K_Parameter_in_the_KNN_Classifier_Using_an_Ensemble_Learning_Approach
if you decide I will send you coed to do it. the distance metric is a problem, because the values varies between 0 and 255, so the light values will dominate the distance, to solve this problem you may use Hassanat distance metric at : https://www.researchgate.net/publication/264995324_Dimensionality_Invariant_Similarity_Measure
because it is invariant to scale in data, as each feature output a value between 0 and 1 no more, thus the highest values will not dominate the final distance.
Good luck

Related

Remove outliers in an image after applying treshold

Here`s the deal. I want to create a mask that visualizes all the changes between two images (GeoTiffs which are converted to 2D numpy arrays).
For that I simply subtract the pixel values and normalize the absolute value of the subtraction:
Since the result will be covered in noise, I use a treshold and remove all pixels with a value below a certain limit.
def treshold(array, thresholdLimit):
print("Treshold...")
result = (array > thresholdLimit) * array
return result
This works without a problem. Now comes the issue. When applying the treshold, outliers remain, which is not intended:
What is a good way to remove those outliers?
Sometimes the outliers are small chunks of pixels, like 5-6 pixels together, how could those be removed?
Additionally, the images I use are about 10000x10000 pixels.
I would appreciate all advice!
EDIT:
Both images are landsat satelite images, covering the exact same area.
The difference here is that one image shows cloud coverage and the other one is free of clouds.
The bright snakey line in the top right is part of a river that has been covered by a cloud. Since water bodies like the ocean or rivers are depicted black in those images, the difference between the bright cloud and the dark river results in the river showing a high degree of change.
I hope the following images make this clear:
Source tiffs :
Subtraction result:
I also tried to smooth the result of the tresholding by using a median filter but the result was still covered in outliers:
from scipy.ndimage import median_filter
def filter(array, limit):
print("Median-Filter...")
filteredImg = np.array(median_filter(array, size=limit)).astype(np.float32)
return filteredImg
I would suggest the following:
Before proceeding please double check if the two images are 100% registered. To check that you should overlay them using e.g. different color channels. Even minimal registration errors can render your task impossible
Smooth both input images slightly (before the subtraction). For that I would suggest you use standard implementations. Play around with the filter parameters to find an acceptable compromise between smoothness (or reduction of graininess of source image 1) and resolution
Then try to match the image statistics by applying histogram normalization, using the histogram of image 2 as a target for the histogram of image 1. For this you can also use e.g. the OpenCV implementation
Subtract the images
If you then still observe obvious noise, look at the histogram of the subtraction result and see if you can relate the noise to intensity outliers. If you can clearly separate signal and noise based on intensity, apply again a thresholding (informed by your histogram). Alternatively (or additionally), if the noise is structurally different from your signal (e.g. clustered), you could look into morphological operations to remove it.

How MNIST really work?

I am working on a digit detection software and I am need to use the MNIST dataset together with TensorFlow.
To predict the numbers I have to do some pre-processing to the images. There are many scripts on the web which have this step inside (the preprocess) but no one of these, at least all what I have tried for now, do what original documentation speak about.
More or less, all the tutorials are based on a theory: the images have to be 28x28 pixels. Which is ok...Maybe..
The documentation tell this about how the MNIST dataset was made:
The original black and white (bilevel) images from NIST were size
normalized to fit in a 20x20 pixel box while preserving their aspect
ratio. The resulting images contain grey levels as a result of the
anti-aliasing technique used by the normalization algorithm. the
images were centered in a 28x28 image by computing the center of mass
of the pixels, and translating the image so as to position this point
at the center of the 28x28 field.
And at this point, this is what I tried to do at my images, to have a 1:1 ratio between MNIST an my ROI.
I create a blank canvas of 28x28 pixels. I took my image (which could be 17x34, it's an example to say that are all rectangular) and resized it to 20x20, without maintaing the ratio between height and width.
I calculate the center of mass of this new (squared) ROI and then I paste it into the center of my 28x28 canvas, in a way that the center of mass and the center of the canvas match.
Above there is the original ROI (rectangles as result of cropping process) and below the output of preprocessing. Note: the red square does not exist, it's just to highlight.
These images, passed to TensorFlow, are being recognized well (~96%). These.
I have other numbers...
The blue ones are being recognized with a low percentage (from a range of 80% to 30%) and the red is not recognized (or recognized wrong with a high percentage).
Example: 5,1,4 are recognized as 7,2,6.
My question is this: what I am doing wrong ? Is the center of mass working good (I am asking this because, for some numbers it traslate the 20x20 ROI down the Y axis and I am correcting this manually) ?
Any help is really welcome and appreciated.
P.S: here you can find some numbers NOT pre-processed so you can test.
P.P.S: I am asking this because, for numbers that it don't recognize, if I move/traslate them by 1/2/3 pixels (really, it's matter of few) up or down, TF work good. Why ?

Finding waters edge using OpenCV and Python accurately

I have been working on trying to detect the edge of the water using OpenCV/Python, and the results I am getting are fairly inaccurate and there is no robustness.
This is what I have achieved so far:
Original Image, output image
Canny Edge detection
What I am currently doing is setting some variables (the level of Gaussian blur, the sigma used for the Canny edge detection, and the maximum deviation which the level measured can change between each point), performing an 'automatic' Canny edge detection (where the median pixel intensity is measured and used to form the lower and upper boundaries), then moving from the bottom left hand corner upwards to find the first 'white' pixel. This is done in x intervals of five the entire length of the frame.
The average y value of the points is the calculated. Each point is then tested to see if it deviates too far from the average pixel, with the deviation limit being set earlier. The remaining points are then drawn on the image as the blue line. The average value of the drawn pixels is recorded at each frame.
After 30 frames, the average of the averages is calculated and drawn as the red line, which is then assumed to be the 'real' water height.
Has anyone have any ideas on a better way to do this? What would make the edge of the water stand out more? This method works on most footage I have recorded, but with poor results.
Thanks in advance.
I have worked on a similar problem and I hope these advices can help you in some way:
Try to restrict your search area: can you make assumptions on where the water level should be? Consider also to have correctly detected the water level. Is it safe to assume that in the next frames the water level will decrease/increase constantly? Will it change slowly? Crop your image in order to take into consideration only the area where it is safe to assume that the water level is present.
Change color space: you can try to work in other color spaces like HSV in order to have the brightness separated from the chromaticity
Hough Transform line detection: try to use this algorithm to search for specific horizontal lines in the image, or other shapes.
Image undistortion: if necessary try to correct the image in order to rectify the curved lines, or cancel the perspective with an Inverse Perspective Mapping (IPM).
You can also consider to change edge detection algorithm.

Object (simple shapes) Detection in Image

I've got the following image.
Other Samples
I want to detect the six square-shaped green portions and the one circular portion above them. I basically want a binary image with these portions marked 1 (white) and everything else 0 (black).
What have I done so far?
I found a range of H, S, and V within which these colors fall which works fine for a single image, but I've got multiple such images, some under different illumination (brightness) conditions and the ranges do not work in those cases. What should I do to make the thresholding as invariant to brightness as possible? Is there a different approach I should take for thresholding?
What you did was manually analyze the values you need for thresholding for a specific image, and then apply that. What you see is that analysis done on one image doesn't necessarily fit other images.
The solution is to do the analysis automatically for each image. This can be achieved by creating a histogram for each of the channels, and if you're working in HSV, I'm guessing that the H channel would be pretty much useless in this case.
Anyway, once you have the histograms, you should analyze the threshold using something like Lloyd-Max, which is basically a K-Means type clustering of intensities. This should give the centroids for the intensity of the white background, and the other colors. Then you choose the threshold based on the cluster standard deviation.
For example, in the image you gave above, the histogram of the S channel looks like:
You can see the large blob near 0 is the white background that has the lowest saturation.

Segmentation of defective areas in grayscale images, which is invariant to shadows

I want to segment defective areas in images using MATLAB/Python-OpenCV.
Original image:
With Defects:
http://imgur.com/fyDkpcZ
Defect can be seen at 3rd rectangle.
What I tried so far:
Extract borders of rectangles with LoG filter / threshold graylevel (but not helps much because of shadows)
Trace their boundaries
Get centroid
Find distance between boundary points and centroid with respect to angle ( increment angle by 0.5 degrees for better resolution)
Find a good template rectangle and save it
Find the difference between template rectangle and candidate rectangle
Based on that result I can find the faulty regions but the false-alarm rate increases when I try to increase the sensitivity of algorithm.
I need to get boundaries much more precise and non-noisy. Because of the shadows, the edges of rectangle may vary vastly.
How can I get edges of rectangles more robust to shadows?
What can be done instead of what I tried so far?
Thanks for your help!
A Laplace of Gaussian filter is a zero mean operation. If you feed it an 8-bit image with intensities centered on 127, it will return you image data centered on zero. You must use a filter bias of arbitrary value, usually half the container's max value (so in this 8-bit example, the bias would be 127). You can also adjust the filter strength by multiplying the result pixels by a constant, this makes the log filter's effect more apparent.
The log filter will make one white and one black edge for very strong transitions. In the horizontal or vertical direction, finding the actual edge is very easy, as you need only take the average of position of both. This gives you sub-pixel resolution if integrated over a small distance.
If the illumination of these images is very similar, you can use registration and subtraction:
Normalize both the image suspected to contain defects and a reference image to some intensity.
Register (align) them; you could do this by detecting three points on a rectangle and then moving and rotating one of the images.
Subtract the suspect image from the reference image. This gives you an error map. You can apply a small blur and then a tight LoG filter to it to remove noise and make detection more accurate.

Categories

Resources