Reputation: 1002
I have the following image:
I want to find the white center of the different periodic features. I marked little red dots of what I'm trying to find. The blurry ones around the edges, I don't care about. Only the middle features. What openCv method would be best to accomplish what I want?
I tried using this method on my image, but the results were not even close.
Thanks to the answers below, I was able to come up with this as a solution (Using OpenCV sharp, a C# library wrapper):
var points = GetPeaks(autoCorrelationImage);
Mat drawContoursMat = autoCorrelationImage.Clone();
foreach(var point in points)
{
Cv2.Circle(drawContoursMat, point, 3, Scalar.red);
}
Methods:
private List<Point> GetPeaks(Mat mat)
{
Mat findPeaksMat = new Mat();
mat.ConvertTo(findPeaksMat, MatType.CV_8UC1);
Cv2.Threshold(findPeaksMat, findPeaksMat, 100, 255, ThresholdTypes.Binary);
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(findPeaksMat, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
var points = ContoursCenter(contours, true);
return points.Where(p => p.X >= 0 && p.Y >= 0).ToList();
}
private List<Point> ContoursCenter(Point[][] contours,bool centerOfMass,int contourIdx = -1)
{
List<Point> result = new List<Point>();
if (contourIdx > -1)
{
if (centerOfMass)
{
Moments m = new Moments(contours[contourIdx], true);
result.Add(new Point(m.M10/m.M00, m.M01/m.M00));
}
else
{
Rect rct = Cv2.BoundingRect(contours[contourIdx]);
result.Add(new Point(rct.X + rct.Width / 2 , rct.Y + rct.Height / 2));
}
}
else
{
if (centerOfMass)
{
for (int i = 0; i < contours.Length; i++)
{
Moments m = new Moments(contours[i], true);
result.Add(new Point(m.M10 / m.M00, m.M01 / m.M00));
}
}
else
{
for (int i = 0; i < contours.Length; i++)
{
Rect rct = Cv2.BoundingRect(contours[i]);
result.Add(new Point(rct.X + rct.Width / 2 , rct.Y + rct.Height / 2));
}
}
}
return result;
}
Upvotes: 1
Views: 208
Reputation: 3115
This problem is pretty straight forward. You could use either of the two methods:
Note: Since you haven't added the original image, I have taken the image from another answer here! If you do attach the original image, I'd be happy to adjust the answer suitably.
The code:
import cv2
import numpy as np
arr = cv2.imread("U:/SO/Lvw2I.png")`
imgray = cv2.cvtColor(arr, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
# Based on contours
im2, contours, heirarchy = cv2.findContours(thresh, cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) > 120:
cv2.drawContours(arr, [cnt], 0, (0, 255, 0), 3)
# Based on CCA
labelnum, labelimg, contours, GoCs = cv2.connectedComponentsWithStats(imgray)
for label in range(1, labelnum):
x, y = GoCs[label]
x, y, w, h, size = contours[label]
if size >= 180:
img = cv2.rectangle(imgray, (x, y), (x+w, y+h), (255, 255, 0), 1)
Results:
Hope it helps!
Upvotes: 2
Reputation: 18331
I think thresholding the image, finding the contours, filtering the contours by the area and calculating the centers
will do the job.
Upvotes: 4