I did color segmentation to my image using java OpenCV and the thresholded image can be shown as image 1 :
I want to calculate the number of white spot in the threshold image. I worked on the findcontour() function and tried to get the count of the white spot. However I failed on that. Please help me. My code is here.
Imgproc.findContours(destination, contours, hierarchy,
Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE);
for(int j=0;j<contours.size();j++){
sum=sum+contours.size();
}
System.out.println("Sum"+sum);
Jeru's answer is correct for this case. If you have a case with bigger noise where morpholigocal operations won't take them out, you can make a cutoff with the contour size, something like
for contour in contours
if cv2.contourArea(contour) > minimal_length
before counting
Related
I am trying to process an X-ray image.
The task is to paint each bone to a different color. I've used canny filter,otsu binarization and Morphological Image Processing such as erosion, to get this effect:
Now I need to find an algorithm to color each bone. I was thinking about using connected-component labeling or flood fill but these algorithms requires closed area which will be filled with a color, but in my image there are also "almost closed" area to color. I was trying to "close each bone" with Dilation but it doesn't work.
And now I completely do not know what to do with it and how to color bones.
You can try to vectorize your image. I have done something similar and after running simple vectorization, connected components were easy to fill.
You can vectorize directly your input by eg. running Marching Squares on it. It will also create edge image.
While this might not be the exact thing you're looking for, I would recommend a simple edge-finding algorithm. The way I would do this (which may not be the best of the most efficient) is to extract the image into a 2D array of pixels. What you can do is compare the RGB values of each pixel to it's neighboring pixel and then color it a brighter color if the difference is higher. To calculate the difference you can use the 3D version of the 2D pythagorean distance formula. Finding the 'distance' between the RGB values and multiplying it by something to keep the values between 0 and 255, then replacing the pixel which you are comparing to it's surrounding pixels with a pixel with the average of this number for the 8 surrounding pixels.
If this is done correctly, it should produce a result similar to, if not identical to the one you present here.
I want to binarize the bone areas (make the bones areas be 255, and the other areas be 0)
but the gray level distribution is not simple enough(it's brighter in the lower half part) to just find a value and threshold it. So I think if I can detect its complete contours and fill the spaces inside these contours may be an easier way.
Original image:
After applying canny edge detection:
I've tried to find a reasonable way to to got these contours of bones occluded but failed. Please give me advice if any. Thank you very much.
I also need to deal with the issues that if there are two bones overlapping together.
(I apologize i didn't mention this in the very first place..)
I'm considering how can i separate a pair of bones overlapping together:
http://i.imgur.com/dI5s11L.png
Consider using Active Contours (snakes)
It computes "fuzzy" edges by considering both local gradient, and the overall "smoothness"
(this description isn't very accurate, It's just to understand the concept)
I tried in several similar cases and got good results.
The low Contrast to Noise Ratio of your raw image makes the object extraction challenge since the threshold setting may not be robust to every image. Yet I tried to extract the bones in your current figure. Two tricks are applied in my processing:(1) non-linear transform of your image to enhance the bones with low intensity compared with the background; (2) zero padding on the border of your image at the possible bone regions after the canny edge detector is applied. See my code below:
I=rgb2gray(I);
I=double(I);
I=I.^0.6; % non linear transform before canny edge detector
BW=edge(I,'canny');
%%% padding at the possible bone regions
BW(1,BW(2,:)==1)=1;
BW(end,BW(end-1,:)==1)=1;
BW(BW(:,2)==1,1)=1;
BW(BW(:,end-1)==1,end)=1;
%%% padding in order to fill in the bone boundaries
bw2=imfill(padarray(BW,size(BW),'symmetric'),'holes');
bw2=bw2(size(bw,1)+(1:size(bw,1)),size(bw,2)+(1:size(bw,2)));
bw2=bwareaopen(bw2,200); % remove the too small regions
MASK=I>10; % remove the background with very low intensity
figure,imshow(bw2.*MASK)
The result:
Everything looks good except one bone boundary is a little bit messy.
I have a screenshot taken from java.awt.Robot as a java.awt.image.BufferedImage and know there will be a unique 10x10 solid red (same RGB) coloured square somewhere in that screenshot (more likely closer to the middle).
What's an efficient approach to finding its coordinates? Is JavaCV even the right library to use? I found a brute force approach in .net here: Bitmap Detection but I'm wondering if there's a better way.
The first question is, what does it take to recognize the color - is it an exact RGB value, where either the color is an exact match, or it isn't? And will that still be the case if the image is lossy-compressed, for example as a JPEG?
Assuming you can do that, probably you want to do a search that tries to minimize time spent searching areas which won't be fruitful: On an imaginary line between two opposite corners, test the value at each corner and the midpoint; if no match, try at the midpoint between the midpoints and the corners; if no match, divide the space in half vertically or horizontally and try again; once you find a pixel of the right color, have some code that walks the pixels in each direction to determine if it's really 10x10.
Really any sort of search pattern will work; what you probably don't want is a situation where you just start at 0,0 and go 0,1 0,2 ... 1,0 1,2 since that will make matching in the upper left fast and bottom right slow (assuming a coordinate space that starts at the top left).
I would like to detect ellipses with OpenCV for Android, using the Tutorial 2-Basic included with OpenCV 2.4.1 package as a starting point. Note that my ellipse would be a perfect-photoshop one.
From what I understand, using the "HoughCircles" will only find perfect (or so) circles, thus leaving ellipses out.
Any help would be much appreciated as I am a total beginner at OpenCV
This is what I've tried so far
case Sample2NativeCamera.VIEW_MODE_CANNY: (ignore the Canny mode...)
capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME);
Imgproc.HoughCircles(mGray, mCircles, Imgproc.CV_HOUGH_GRADIENT, 1, 20);
Log.d("Ellipse Points", " X " + mCircles.get(1,1)[0] + mCircles.get(1, 1)[1]);
break;
If you think any more info could be useful, please let me know.
One possible solution to your problem is similar to this thread Detection of coins (and fit ellipses) on an image .
You should take a look a opencv's function fitEllipse.
The parameters used in HoughCircles play a fundamental role. HoughCircles will detect not just perfect, but also near-perfect circles (ellipses). I suggest you check this examples:
How to detect circles (coins) in a photo
Simple object detection using OpenCV
OpenCV dot target detection
Reshaping noisy coin into a circle form
And this answer has a decent collection of references.
If you already have an idea of the sizes of the ellipses that you're looking for, then try the following steps:
Find Canny edges in the image
Use a sliding window, the size of which is the maximum length of the major axis of ellipses you're looking for.
Within the window, collect all edge pixels, pick 6 pixels randomly and use linear least squares to fit an ellipse in the general form.
Repeat the above step in a RANSAC like procedure.
If there are enough inliers, you have an ellipse.
I have a gray scale image of 64x64. I found the dots of the contour by a simple algorithm:
find brightest spot (Example: 100)
divide by 2 (100/2 = 50)
define a band around the result (50-5=45 to 50+5=55)
mark all dots that have value in the band (between 45 to 55)
The question now is, how do I decide of the order of connecting the dots?
(All references will be accepted, links, thoughts, etc')
Your algorithm allows the entire image, save for one pixel, to be "the contour". I'm not sure that's exactly what you want; usually a contour is a border between two different regions. The problem with your method is that you can get huge blobs of pixels that have no particularly obvious traversal order. If you have a contour that is a single pixel thick, then the traversal order is much more obvious: clockwise or counterclockwise.
Consider the following image.
........
..%%%%..
.%%%%...
...%%%%.
....%...
........
Here, I've marked everything "dark" (<50, perhaps) as % and everything bright as .. Now you can pick any pixel that is on the border between the two regions (I'll pick the dark side; you can draw the contour on the light side also, or with a little more work, directly between the light and dark sides.)
........
..%%%%..
.*%%%...
...%%%%.
....%...
........
Now you try to travel along the outer edge of the dark region, one pixel at a time. First, you look in the direction of something bright (directly left, for example). Then you rotate around--counterclockwise, let's say--until you hit a dark pixel.
........
..%%%%..
1*5%%...
234%%%%.
....%...
........
Once you hit position 5, you see that it's dark. So, you mark it as part of the contour and then try find the next piece on the contour by sweeping around starting from the pixel you just came from
........
..%%%%..
.0*%%...
.123%%%.
....%...
........
Here 0 is where you came from--and you're not going back there--and then you try pixels 1 and 2 (both light, which is not okay), until you hit pixel 3, which is dark.
In this way, you can walk around the contour pixel by pixel--both identifying the contour and getting the order of pixels--until you collide with the same pixel you started with and will leave from it so that you hit the same pixel that you did the first time you left it. Then the contour is closed. In our example, where we're making an 8-connected contour (i.e. we look at 8 neighbors, not 4), we'd get the following (where # denotes a contour point).
........
..####..
.##%#...
...#%##.
....#...
........
(You have to have this two-in-a-row criterion or if you have a dark region a single pixel wide, you'll walk up it but then not be able to walk back down along it.)
At this point, you've covered one entire boundary. But there might be others. Keep looking for dark pixels next to light ones until you have drawn a contour on top of all of them. Now you've converted your two-level picture (dark & bright pixels) into a set of contours.
If the contours end up too noisy, consider blurring the image first. That will smooth the contours out. (Alternatively, you can find the contours first and then average the coordinates with a moving window.)
In general, a given set of points can be connected in multiple ways to make different shapes.
For example, consider a set of 5 points consisting of the corners of a square and its center. These points can be connected to form a square with one side "dented in" to the center. But which side? There is no unique answer.
Other shapes can be much more complicated, with no obvious way to connect the dots.
If you are allowed to reduce your set of points to a convex hull, then it would be much easier.
I have also tried to create an algorithm that will connect contour dots into the smooth curve. See my open-source project http://outliner.codeplex.com.
The idea is the same as proposed by FUZxxl but I do not understand his worries about complexity: the time of processing is proportional to the total length of all contour strokes.
I don't know if collecting those points will get you far. (I can come up with situations in which it's almost impossible to tell which order they should come in.)
How about going to the brightest point.
Go to the brightness point of, say, 360 points surrounding this point at a distance of, say, 5 pixels.
Continue from there, but make sure you don't go back where you came from :)
Maybe try:
Start at a
Find the nearest point b
Connect a with b
and so on.
Probably not good, as complexity is something like O(n²). You may simplify this by looking only for points near the start, as aioobe suggest. This algorithm is good, if the points are just like 2-3px away from each other, but may create very strange grids.
See also Flood fill
and the lovely applet under SO
mapping-a-branching-tile-path .