How to remove image noise (horizontal lines) while filling the hyperbolas? Idea requested :) - matlab

I have an image as showin in '1'.
I applied Hessian filter to get the result '2'.
I applied Standard filter (stdfilt) in MATLAB to get the result as in '3'.
I wish to combine these two results into a single image such that:
the horizontal lines (noise in my case) are removed.
the hyperbolic areas are filled.
How could I obtain such a result?
Original (1):
Hessian (2):
stdfilt (3):
Last two without markups:

You can start by binarizing your image. I recommend opencv otsu threshold. it will be hard to solve this problem if gradients are present. After the image is binarized, you will need to fix bridging between the parabolas and the horizontal lines. I recommend morphological erosion, but I am still experimenting with this in my own projects. After that, you can use watershed or DBSCAN to flood-fill each region with a given marker or color. You can then filter out the horizontal lines by pixel count, since they will be much larger than a single parabola. If erosion+DBSCAN doesn't work reliably, you can look into opencv's connectedComponents function.
See:
https://iq.opengenus.org/connected-component-labeling/
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html
https://docs.opencv.org/4.x/d3/db4/tutorial_py_watershed.html

Related

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

use scale space representation to filter one image

Currently I hope to use scale space representation to filter one image. Features in one image can be filtered using an Gaussian smooth filter with one optimal sigma. It means different features in one image can be expressed best in different scale under scale space representation.
For example, I have one image with one tree in it. In the scale space representation, three sigma values are used and they are represented as sigma0, sigma1 and sigma2. The ground is best expressed in the smoothed image with sigma0 because it contains textures mainly. The branches are best expressed in the smoother image with sigma1 and the trunk is with the smoother image with sigma2. If I hope to filter the image, I hope that the filtered pixels for the group is from the smoothed image with sigma0.
The filtered pixels for the branches are from the smoothed image with sigma1. The filtered pixels for the trunk are from the smoothed image with sigma2.
It requires that I need to determine in which smoothed image one pixel is expressed best. Is this idea plausible?
I am trying to use differece-of-Gaussian of two successive smoothed images to perform the above task. Is there any other way to combine the three smoothed image?
I use Matlab to implement the idea. The values of the three sigmas is 1.0, 2.0 and 3.0. The corresponding size of Gaussian kernel is 3, 5 and 7. I use the function fspecial to generate the kernel. Are the parameter reasonable? Please share your experience with the scale space representation to help me. You can provide some links to useful papers.
your idea is very much plausible! You are just one step away from it. I did something very similar once and it looked like this:
After smoothing your images and extracting the edges for each smoothing step (I used a weighted [to compensate for maxima supression after Gauss filtering] Sobel filter for this since DOG was not quite stable for my aplication), you can proyect (and normalize) your whole stack of edge images into a single image ("cummulative edges") which will contain the characteristic edges. You can then compare the cummulative edges image (using cross-correlation or whatever you wish) with every single image in your edge stack, the biggest value of this comparation is then the smooth-scale in which the pixel is expressed the best.
Hope that makes sense for you after reading it a couple of times.
Also don't be afraid of using much bigger kernel sizes, while it all depends on your application, I ended up using things of 51 and bigger!!! (was working with 40MP images though...)
T. Lindeberg has literally dozens of papers related to this problem. I found this one the most useful, but since you are already in the right track, I don't think reading the 50 pages will make you that much smarter. The most important part of it is maybe this one:
Principle for scale selection:
In the absence of other evidence, assume that a scale level, at which some
(possibly non-linear) combination of normalized derivatives assumes a
local maximum over scales, can be treated as reflecting a characteristic
length of a corresponding structure in the data.

MATLAB: Using hough transform to detect circle

I am writing a matlab code that takes in a photo and detects the circular object. For example, the function takes a picture of a peach (circular object) as an input and will return the same image with the peach circled.
Currently, I am using hough transform, utilizing imfindcircles function. However, this function requires me to specify radius range and some sort of sensitivity/threshold value. These values differ for different sizes of image and round objects. So, to get the desired output, I will have to manually change these values for each input image, which is not what I want. I'm going to use this function on 100+ images, so it's impossible for me to do this manually.
My question is is there any way I can make my circular object detection function less manual and possibly completely automatic (does not require me to input any values, just the image)?
Complexity of circle detection
The Hough transform is a voting procedure that requires assumptions be made about the minimum and maximum radii of your circles. Generally speaking using the Randomized Hough Transform for Circles you would pick three-points and then try to form a circle and check if the radius is within the desired range. Running this for a good number of iterations you should find peaks (multiple hits) in your accumulator matrix that represent circles. If you didn't make any assumptions about object size I think it is obvious this method wouldn't work.
Do some routine pre-processing to adjust for contrast and brightness e.g. contrast stretching, histogram equalization. If you might have some noise in the images, then apply bit of gaussian smoothing as well.
Normalizing images this way will reduce inter-image variance and help you with setting thresholds.
the Hough Transform can be used to detect circles, lines, etc.You can refer the demos in Matlab. There are several cases for the application of Hough Transform.

Image filtering

I have a problem with removing the line artifact from the OCT image. I trying wiener and median filtering but nothing works well.
In this picture is clearly visible line artifact in both directions.
I have I more picture with I take by averaging 450 images in Z axe.
Can you help me? please.
Another option might be to Fourier filter your image with two masks of sincs (sinc(x)=sin(x)/x) functions for vertical and horizontal lines. On a different note, from what I see you may want to improve data acquisition by understanding where these lines come from (i.e. take a background image, where you "scan" nothing and compensate for shot noise of the detector etc)
Try a Gaussian blur by a few pixels. Then, for each column subtract the median pixel. Repeat for the rows.
If you're talking about the vertical lines then since the lines are quite narrow you could use morphological operators, e.g. 1x7 horizontal erode (min) followed by 1x7 horizontal dilate (max).

How to detect curves in a binary image?

I have a binary image, i want to detect/trace curves in that image. I don't know any thing (coordinates, angle etc). Can any one guide me how should i start? suppose i have this image
I want to separate out curves and other lines. I am only interested in curved lines and their parameters. I want to store information of curves (in array) to use afterward.
It really depends on what you mean by "curve".
If you want to simply identify each discrete collection of pixels as a "curve", you could use a connected-components algorithm. Each component would correspond to a collection of pixels. You could then apply some test to determine linearity or some other feature of the component.
If you're looking for straight lines, circular curves, or any other parametric curve you could use the Hough transform to detect the elements from the image.
The best approach is really going to depend on which curves you're looking for, and what information you need about the curves.
reference links:
Circular Hough Transform Demo
A Brief Description of the Application of the Hough
Transform for Detecting Circles in Computer Images
A method for detection of circular arcs based on the Hough transform
Google goodness
Since you already seem to have a good binary image, it might be easiest to just separate the different connected components of the image and then calculate their parameters.
First, you can do the separation by scanning through the image, and when you encounter a black pixel you can apply a standard flood-fill algorithm to find out all the pixels in your shape. If you have matlab image toolbox, you can find use bwconncomp and bwselect procedures for this. If your shapes are not fully connected, you might apply a morphological closing operation to your image to connect the shapes.
After you have segmented out the different shapes, you can filter out the curves by testing how much they deviate from a line. You can do this simply by picking up the endpoints of the curve, and calculating how far the other points are from the line defined by the endpoints. If this value exceeds some maximum, you have a curve instead of a line.
Another approach would be to measure the ratio of the distance of the endpoints and length of the object. This ratio would be near 1 for lines and larger for curves and wiggly shapes.
If your images have angles, which you wish to separate from curves, you might inspect the directional gradient of your curves. Segment the shape, pick set of equidistant points from it and for each point, calculate the angle to the previous point and to the next point. If the difference of the angle is too high, you do not have a smooth curve, but some angled shape.
Possible difficulties in implementation include thick lines, which you can solve by skeleton transformation. For matlab implementation of skeleton and finding curve endpoints, see matlab image processing toolkit documentation
1) Read a book on Image Analysis
2) Scan for a black pixel, when found look for neighbouring pixels that are also black, store their location then make them white. This gets the points in one object and removes it from the image. Just keep repeating this till there are no remaining black pixels.
If you want to separate the curves from the straight lines try line fitting and then getting the coefficient of correlation. Similar algorithms are available for curves and the correlation tells you the closeness of the point to the idealised shape.
There is also another solution possible with the use of chain codes.
Understanding Freeman chain codes for OCR
The chain code basically assigns a value between 1-8(or 0 to 7) for each pixel saying at which pixel location in a 8-connected neighbourhood does your connected predecessor lie. Thus like mention in Hackworths suggestions one performs connected component labeling and then calculates the chain codes for each component curve. Look at the distribution and the gradient of the chain codes, one can distinguish easily between lines and curves. The problem with the method though is when we have osciallating curves, in which case the gradient is less useful and one depends on the clustering of the chain codes!
Im no computer vision expert, but i think that you could detect lines/curves in binary images relatively easy using some basic edge-detection algorithms (e.g. sobel filter).