I generated a hotspot map as shown here and now I want to calculate the area of each significant hotspot region. From the little research I've done, it seems as though I need to treat the contours as convex hulls and use Green's Theorem to calculate the area of the convex hulls.
However, I don't know how to translate this procedure into python code. Is there an easier method to achieve my goal?
I'm thinking of isolating all convex hulls that contain intensity greater than 3.2 (that is light blue, green, yellow, orange and red colors) and finding the area enclosed in those contours.
I would also like to count the number of points contained in the convex hulls generated.
Is there a simple way to do this using matplotlib?
Related
I have a task of identifying the number of bacterial colonies on a relatively diverse set of top-down photos of a Petri dish located on a table. The basic process is the following:
detect the Petri dish on the image, crop everything outside of it;
apply binary thresholding which should result in a black background and white colonies or clusters thereof;
use simple blob detector or watershed to identify the colonies, highlight them on the source image and output their count.
Input example 1 Input example 2 Input example 3: an edge case
Problem 1
The table around the Petri dish isn't smooth and contains spots so I usually use Hough transform to detect the dish and remove everything outside of it. The problem is that there are light reflections near the edge of the Petri dish represented as rings with their radius on par with that of the dish edge, as well as other reflections that obscure the view of the colonies and affect the thresholding applied. So I need reliable code for detecting the innermost circle that has roughly the same centre as the outer border of the Petri dish and doesn't contain any further reflections, i.e. cropping at the outer border is sub-optimal.
Cropping attempt
fig. 1. Grab first detected circle with a radius within the range of [int(image.shape[1]/4),int(image.shape[1]/2)] from circle Hough Transform, use a mask and crop to [x+r:x-r,y+r:y-r]
Problem 2.1
The colonies have a colour usually close to the colour of the background (the agar) and in different areas these can overlap (e.g. colony colour in a section A has the same colour as the background in a section B). This renders the method of general thresholding useless. Different photos having different brightness is an issue as well in the context of the binary method and its rigid parameters - for some images a param of (184,255) is useful while on others only a setting as low as (120,255) results in something half-usable.
Gaussian blur, pyrmeanshift, binary threshold
fig 2.1. Gaussian blur (3,3) + pyrmeanshift (6,27) + binary threshold (205,255)
Problem 2.2
The bacterial colonies have round shapes which sometimes form clusters of overlapping circles so the simple blob detector tends to ignore those. The algorithm is supposed to detect the cluster and identify how many colonies (circles) are in it. To tackle this, I've tried Euclidean distance transform coupled with watershed as an alternative to simple blob detector but this needs to be fed a clean image not containing anything other than the colonies themselves, so a robust threshold algorithm is required for removing all the light reflections and eliminating the background's (agar's) gradient. There are also many spots on the Petri dish usually smaller in size than the colonies and not really round - these should be ignored by the detector algorithm. I've heard of adaptive thresholding used for overcoming the problem of a varied background but this tends to convert non-colony small spots on the dish into full-fledged circles which isn't very optimal.
Adaptive threshold - Gaussian method
fig 2.2. Adaptive threshold (Gaussian C)
An attempt at detecting colonies on input example 2
fig 3. A failed attempt at using watershed with distance transform, demonstrating that this algorithm requires a well cleaned-up and properly thresholded input
I'm interested to know whether this task is feasible in the context of a varied collection of photos taken in different lighting conditions as well as different colonies having different sizes and colours. If so, what ways are there to approach this?
Say we have the following contour information from OpenCV contours:
What I mean by a "region" is a subset of the contour with low directional variation.
So for example these, could be regions in the provided example:
One way to detect these could be, doing a local neighborhoud comparison of the dot products of the tangent at each point. (i.e see how much the tangent changes locally).
I was wondering however if there is a better way to do this, using OpenCV directly rather than doing vector operations myself.
-When your region boundaries are always near-vertical or near-horizontal, consider preprocessing the image using a filter (erode, dilate), to isolate vertices and horices, then merge results, to find an alternating color on region boundaries.
-When your directions go anywhere, it's more complicated ! One option would be to retrieve coordinates from your pixels with the help of Hough lines see
https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html
I have an input image which consists of 3 colors.These colors are circular in shape and nested.
The image is similar to this :
https://www.google.ie/search?q=red+yellow+blue+nested+circles&client=ms-unknown&tbm=isch&tbs=rimg:CbQTsOKsM7yhIkCaDOdJHzqnN2Xk-DhItFHm0Zqt6wMB32Tm1CzyzQ7wrXERbVqngEyMBzO57J8UuHLak9WPqWfjV7kgvdJ47BJlKhIJmgznSR86pzcR8SW2ldYWlqIqEgll5Pg4SLRR5hG-6WlMFrVBvioSCdGaresDAd9kEVFfCyyB-AgqKhIJ5tQs8s0O8K0RT790ELynuK8qEglxEW1ap4BMjBHBPar4Jd2NtioSCQczueyfFLhyEY7iP_13IGcsOKhIJ2pPVj6ln41cRTMOWeqZE5oYqEgm5IL3SeOwSZREray5kAy-dzw%3D%3D&tbo=u&ved=0ahUKEwjWzfSC6IbXAhXFbBoKHW3GBrUQuIIBCCM#imgrc=5tQs8s0O8K32hM:
I will be working with several images like this.The imaage is always of the same thing.however dude to different camera , lighting , even printer differences , the actual color can vary. In that it will always be red yellow green in the order showen. By using HSV and thresholds I can easily determine upper and lower values for each color. However If I change to a different set of images theses values are no longer functional.
My idea to overcome this is to look for contours first in the image.
For each contour I would like to get an upper and lower threshold. Using a combination of canny , gaussian and contours I am able to draw contour around each color from testing this seems general enough for purpose.
Where I'm stuck is getting the threshold value from within the contours. Is this possible? Or is there simpler logic I am over looking to achieve this ?
At present I'm using python , but language is secondary.
Forget about the contours, they will make things harder than necessary.
A better approach could be by classifying the pixels using k-means. Initialize with at least three clusters, centered around green, yellow, red. Maybe one centered on white, for the background.
After convergence you should have the exact colors, together with segmentation.
https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm
I have a figure that I get contour lines from a picture of face use by opencv (image below). I need to determine most curvature points of this contour in python (in the image, I need to define the red dots on right of the red line). How can I do it ?
Just find contour and compute curvature then find maximums: curvature
This article also may be useful: article
How can I extract the boundary curve of an image region enumerated by measure.regionprops?
By boundary curve, I mean a list of border pixels of the region in, say, clockwise direction around the region's perimeter, such that I can, for example, represent the region with a polygon. Note that I want the exact coordinates of all border pixels, not a convex hull approximation.
I've read the docs and googled, and I have the impression its done somewhere under the hood, but I just cannot find the function.