Corner detection not accurate - java

I'm trying to detect corners, but the coordinates I get are always off-center and saddle-points are detected Multiple times.
I tried cornerHarris, cornerMinEigenVal, preCornerDetect, goodFeaturesToTrack, and cornerEigenValsAndVecs, but they all seem to lead to the same result. I haven't tried findChessboardCorners because my corners are not laid out in a nice grid of n×m, are not all saddle-type, and many more reasons.
What I have now:
Given the (pre-processed) camera image below with some positive, negative, and saddle corners:
After cornerHarris(img, energy, 20, 9, 0.1) (I increased blockSize to 20 for illustrative purposes but small values don't work either) I get this image:
It seems to detect 10 corners but the way they are positioned is odd. I superimposed this image on the original to show my problem:
The point of highest matching energy is offset towards the inside of the corner and there is a plume pointing away from the corner. The saddle corners seem to generate four separate plumes all superimposed.
Indeed, when I perform a corner-search using this energy image, I get something like:
/
What am I doing wrong and how can I detect corners accurately like in this mock image?
[[edit]] MCVE:
public class CornerTest {
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
private static Mat energy = new Mat();
private static Mat idx = new Mat();
public static void main(String... args) {
Mat byteImage = Highgui.imread("KXw7O.png");
if (byteImage.channels() > 1)
Imgproc.cvtColor(byteImage, byteImage, Imgproc.COLOR_BGR2GRAY);
// Preprocess
Mat floatImage = new Mat();
byteImage.convertTo(floatImage, CvType.CV_32F);
// Corner detect
Mat imageToShow = findCorners(floatImage);
// Show in GUI
imageToShow.convertTo(byteImage, CvType.CV_8U);
BufferedImage bufImage = new BufferedImage(byteImage.width(), byteImage.height(), BufferedImage.TYPE_BYTE_GRAY);
byte[] imgArray = ((DataBufferByte)bufImage.getRaster().getDataBuffer()).getData();
byteImage.get(0, 0, imgArray);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new JLabel(new ImageIcon(bufImage)));
frame.pack();
frame.setVisible(true);
}
private static Mat findCorners(Mat image) {
Imgproc.cornerHarris(image, energy, 20, 9, 0.1);
// Corner-search:
int minDistance = 16;
Core.MinMaxLocResult minMaxLoc = Core.minMaxLoc(
energy.submat(20, energy.rows() - 20, 20, energy.rows() - 20));
float thr = (float)minMaxLoc.maxVal / 4;
Mat tmp = energy.reshape(1, 1);
Core.sortIdx(tmp, idx, 16); // 16 = CV_SORT_EVERY_ROW | CV_SORT_DESCENDING
int[] idxArray = new int[idx.cols()];
idx.get(0, 0, idxArray);
float[] energyArray = new float[idx.cols()];
energy.get(0, 0, energyArray);
int n = 0;
for (int p : idxArray) {
if (energyArray[p] == -1) continue;
if (energyArray[p] < thr) break;
n++;
int x = p % image.cols();
int y = p / image.cols();
// Exclude a disk around this corner from potential future candidates
int u0 = Math.max(x - minDistance, 0) - x;
int u1 = Math.min(x + minDistance, image.cols() - 1) - x;
int v0 = Math.max(y - minDistance, 0) - y;
int v1 = Math.min(y + minDistance, image.rows() - 1) - y;
for (int v = v0; v <= v1; v++)
for (int u = u0; u <= u1; u++)
if (u * u + v * v <= minDistance * minDistance)
energyArray[p + u + v * image.cols()] = -1;
// A corner is found!
Core.circle(image, new Point(x, y), minDistance / 2, new Scalar(255, 255, 255), 1);
Core.circle(energy, new Point(x, y), minDistance / 2, new Scalar(minMaxLoc.maxVal, minMaxLoc.maxVal, minMaxLoc.maxVal), 1);
}
System.out.println("nCorners: " + n);
// Rescale energy image for display purpose only
Core.multiply(energy, new Scalar(255.0 / minMaxLoc.maxVal), energy);
// return image;
return energy;
}
}

Related

Java OpenCV detect and crop circullar/elliptical shapes

I am trying to detect and crop circullar/elliptical shapes of different sizes.
This is an example of an image I am trying to do the detection and croping.
Input Image
The result I am trying to get in the aforementioned image is 3 cropped images
looking like this:
segmented part 1, segmented part 2, segmented part 3
Another image could look like this: different image
Just like the previous image, I am trying to do the same to this one.
The shapes are dramatically smaller from the first one.
Can this be achieved algorithmically or should I look for a machine learning-like solution?
Note: The final image has been applied by the following filters: Gaussian Blur, Grayscale, Threshold, Contour and Morphological Dilation.
[EDIT]
The code I have written(not working as intended):
findReference() finds a shape in the middle of the image and returns its rectangle.
private Rect findReference(Mat inputImage) {
// clone the image
Mat original = inputImage.clone();
// find the center of the image
double[] centers = {(double)inputImage.width()/2, (double)inputImage.height()/2};
Point image_center = new Point(centers);
// finding the contours
ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(inputImage, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// finding best bounding rectangle for a contour whose distance is closer to the image center that other ones
double d_min = Double.MAX_VALUE;
Rect rect_min = new Rect();
for (MatOfPoint contour : contours) {
Rect rec = Imgproc.boundingRect(contour);
// find the best candidates
if (rec.height > inputImage.height()/2 & rec.width > inputImage.width()/2){
continue;
}
Point pt1 = new Point((double)rec.x, (double)rec.y);
Point center = new Point(rec.x+(double)(rec.width)/2, rec.y + (double)(rec.height)/2);
double d = Math.sqrt(Math.pow((double)(pt1.x-image_center.x),2) + Math.pow((double)(pt1.y -image_center.y), 2));
if (d < d_min)
{
d_min = d;
rect_min = rec;
}
}
// showReference( rect_min, original);
return rect_min;
}
I use the rectangle as reference and create a bigger one and a smaller one, so that similar shapes fit in the dimensions of the smaller and bigger rectangle.
findAllEllipses() tries to find similar shapes fitting in the smaller and bigger rectangles. After that it draws ellipses around the found shapes.
private Mat findAllEllipses(Rect referenceRect, Mat inputImage) {
float per = 0.5f;
float perSquare = 0.05f;
Rect biggerRect = new Rect();
Rect smallerRect = new Rect();
biggerRect.width = (int) (referenceRect.width / per);
biggerRect.height = (int) (referenceRect.height / per);
smallerRect.width = (int) (referenceRect.width * per);
smallerRect.height = (int) (referenceRect.height * per);
System.out.println("reference rectangle height: " + referenceRect.height + " width: " + referenceRect.width);
System.out.println("[" + 0 +"]: biggerRect.height: " + biggerRect.height + " biggerRect.width: " + biggerRect.width);
System.out.println("[" + 0 +"]: smallerRect.height: " + smallerRect.height + " smallerRect.width: " + smallerRect.width);
//Finding Contours
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchey = new Mat();
Imgproc.findContours(inputImage, contours, hierarchey, Imgproc.RETR_TREE,
Imgproc.CHAIN_APPROX_SIMPLE);
System.out.println("the numbers of found contours is: " + contours.size());
int sum = 0;
//Empty rectangle
RotatedRect[] rec = new RotatedRect[contours.size()];
for (int i = 0; i < contours.size(); i++) {
rec[i] = new RotatedRect();
if(contours.get(i).toArray().length >= 5 ){
Rect foundRect = Imgproc.boundingRect(contours.get(i));
// Rect foundBigger = new Rect();
// Rect foundSmaller = new Rect();
//
// foundBigger.width = (int) (foundBigger.width + foundBigger.width * per);
// foundBigger.height = (int) (foundBigger.height + foundBigger.height * per);
//
// foundSmaller.width = (int) (foundRect.width - foundRect.width * per);
// foundSmaller.height = (int) (foundRect.height - foundRect.height * per);
if (
(biggerRect.height >= foundRect.height && biggerRect.width >= foundRect.width)
&& (smallerRect.height <= foundRect.height && smallerRect.width <= foundRect.width)
&& (((foundRect.width - foundRect.width * perSquare) <= foundRect.height) && ((foundRect.width + foundRect.width * perSquare) >= foundRect.height))
&& (((foundRect.height - foundRect.height * perSquare) <= foundRect.width) && ((foundRect.height + foundRect.height * perSquare) >= foundRect.width))
) {
System.out.println("[" + i +"]: foundRect.width: " + foundRect.width + " foundRect.height: " + foundRect.height);
System.out.println("----------------");
rec[i] = Imgproc.fitEllipse(new MatOfPoint2f(contours.get(i).toArray()));
sum++;
}
}
Scalar color_elli = new Scalar(190, 0, 0);
Imgproc.ellipse(inputImage, rec[i], color_elli, 5);
}
System.out.println("found ellipses: " + sum);
// trytest(ImageUtils.doResizeMat(outputImage),0,0);
return inputImage;
}
Unfortuantelly there are several variables that are hardcoded into the method.
This is used to make the smaller and bigger rectangles (used as a percentage)
float per = 0.5f;
perSquare is used to get shapes closer to a square (fluctuated width height)
float perSquare = 0.05f;
This code might work in some images, while on others will not find a single shape, like I mentioned the shapes are circullar/elliptical and of different sizes.

How to calculate intersection points based on corners and number of cells

I am trying to find all intersection points (their x and y values) based on 4 corner points that I always have and number of cells (in my case 9, so 9x9 matrix, sudoku puzzle).
My 4 corners are marked with green cross, and taged P1 to P4.
I tried to calculate it, and only managed to do it precisely for the first row.
double xDis = p2.x - p1.x;
double yDis = p2.y - p1.y;
double xW = xDis / 9;
double yH = yDis / 9;
for (int i = 0; i < 10; i++) {
Point point = new Point(p1.x + (i * xW), p1.y + (i * yH));
}
This code would work exactly as I expected it but only for the first row.
What am I missing here ? Is there some kind of algoritmh that already does this ? Any hints are welcome.
Note that I am using android with OpenCV library.
As written above in the comments, I ended up warping the image and then cutting it. It looks something like this
if (points != null) {
Point p1 = points[0];
Point p2 = points[1];
Point p3 = points[2];
Point p4 = points[3];
MatOfPoint2f src = new MatOfPoint2f(
p1,
p2,
p3,
p4);
drawMarker(frame, p1, new Scalar(255,0,0), 0, 20, 1);
drawMarker(frame, p2, new Scalar(255,0,0), 0, 20, 1);
drawMarker(frame, p3, new Scalar(255,0,0), 0, 20, 1);
drawMarker(frame, p4, new Scalar(255,0,0), 0, 20, 1);
double x = p2.x - p1.x;
double y = p3.y - p2.y;
MatOfPoint2f dst = new MatOfPoint2f(
new Point(0, 0),
new Point(x,0),
new Point(0,y),
new Point(x,y)
);
Mat warpMat = Imgproc.getPerspectiveTransform(src, dst);
//This is you new image as Mat
Mat destImage = new Mat();
Imgproc.warpPerspective(bw2, destImage, warpMat, new Size(x, y));
List<Mat> cells = getCells(destImage, destImage.width() / 9, destImage.height / 9);
}
private List<Mat> getCells(Mat m, int width, int height) {
Size cellSize = new Size(width, height);
List<Mat> cells = new ArrayList<>();
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
Rect rect = new Rect(new Point(col * width, row * height), cellSize);
Mat digit = new Mat(m, rect).clone();
cells.add(digit);
}
}
return cells;
}
You only do your calculation once, on the first row.
Put your for loop inside of another for loop and run it 10 times, and you should be good (Adding in whatever x,y translation happens as you traverse downwards in y).
As for if there is any automated way to do this, yes. I could suggest using Harris Corner Detection. I suspect using the right thresholds could get you only the thicker line corners. You could also try doing line detection and looking for intersections.
Also, this article may be helpful if you find you aren't finding good lines/corners. You can correct the shading from the lighting and get a good clean image to analyze.

Java: Drawing a Star and Connecting Points w/Drawing Panel

I am having issues figuring out three things. (Created using Drawing Panel: http://www.buildingjavaprograms.com/DrawingPanel.java)
Problem #1: Drawing the polygon so it's centered and not crooked. It's unnoticeable with more points drawn.
Problem #2: Connecting all points of the star together so it's a giant circle (dotted). I don't see why it's happening unless maybe the method is not the best.
Problem #3: When drawn with low amounts of points, I notice that it doesn't draw a point correctly, and it looks like a square.
I'd really appreciate the help!
import java.awt.*;
public class StarSampler {
public static void main(String[] args)
{
DrawingPanel panel = new DrawingPanel(500, 500);
Graphics2D g = panel.getGraphics();
g.setColor(Color.BLUE);
fillStar(g, 250, 250, 150, 5, 1);
}
public static void fillStar(Graphics2D g, int ctrX, int ctrY, int radius, int nPoints, double spikiness)
{
double xDouble[] = new double[2*nPoints];
double yDouble[] = new double[2*nPoints];
int xPoint[] = new int[100];
int yPoint[] = new int[100];
for (int i = 0; i < 2*nPoints; i++)
{
double iRadius = (i % 2 == 0) ? radius : (radius * spikiness);
double angle = (i * 720.0) / (2*nPoints);
xDouble[i] = ctrX + iRadius * Math.cos(Math.toRadians(angle));
yDouble[i] = ctrY + iRadius * Math.sin(Math.toRadians(angle));
for (int j = 0; j < nPoints; j++) // Casts for ints and doubles
{
xPoint[j] = (int) xDouble[j];
yPoint[j] = (int) yDouble[j];
}
}
g.fillPolygon(xPoint, yPoint, nPoints); // Creates polygon
// Polygon gets drawn crookedly
g.drawPolyline(xPoint, yPoint, nPoints); // Draws lines to connect points
// Two lines go straight to (0,0) when nPonts*2 and nothing without *2?
}
}
My Output:
My Target Output (Without labeled points, two stars just for example):
The issues with your code are of logical nature or due to a sloppy coding style:
for (int j = 0; j < nPoints; j++) // Casts for ints and doubles
{
xPoint[j] = (int) xDouble[j];
yPoint[j] = (int) yDouble[j];
}
This piece of code is supposed to transform all portions of the polygon into integers. There are several issues with this piece of code:
It doesn't cover all points. The loop produces a total of 2 * nPoints points, but only half of them is converted. This is where the missing spikes come from
Why do this in a inner loop? This shouldn't be done in the loop that generates the values. It's just an enormous number of redundant copies and casts.
Why keep two separate arrays at all? Just convert them directly on creation. Since no value will be reused, there's no point in keeping a value with full precision anyways.
A circle is 360 degrees, not 720. This code:
double angle = (i * 720.0) / (2*nPoints);
Will alter the angle between created points. This means you either only generate half of the spikes, if the number is even, or generate a lot of crossing lines (doesn't look bad either, but not what you want, I guess).
The unit-circle (relevant for the trignometry-part) is defined in a way such that (1, 0) is the point with an angle of 0° to the center. This is also where your first spike will be created. Simply substract 90° of the angle to rotate the circle by 90° counter-clockwise.
Here's working solution based on your code. The main-method only holds the code to manage a simple testing-UI:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class StarSampler
{
private static final int WIDTH = 500,
HEIGHT = 500,
RADIUS = 200;
private static final double SPIKINESS = 0.5;
public static void main(String[] args)
{
BufferedImage bi = new BufferedImage(500, 500, BufferedImage.TYPE_4BYTE_ABGR);
updateImage(5, bi);
JFrame frame = new JFrame("Some Test");
frame.setLayout(new BorderLayout());
frame.add(new JLabel(new ImageIcon(bi)), BorderLayout.CENTER);
//menu to update number of spikes
JPanel sub = new JPanel();
sub.setLayout(new BoxLayout(sub, BoxLayout.X_AXIS));
sub.add(new JLabel("Spikes: "));
JSpinner spikeSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 500, 1));
spikeSpinner.addChangeListener(e -> {
updateImage((Integer) spikeSpinner.getModel().getValue(), bi);
SwingUtilities.invokeLater(()->frame.repaint());
});
sub.add(spikeSpinner);
frame.add(sub, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static void updateImage(int nSpikes, BufferedImage bi)
{
int ctrX = WIDTH / 2, ctrY = HEIGHT / 2;
int nPoints = nSpikes * 2 + 1;
int xPoint[] = new int[nPoints];
int yPoint[] = new int[nPoints];
//generate star
for (int i = 0; i < nPoints; i++)
{
double iRadius = (i % 2 == 0) ? RADIUS : (RADIUS * SPIKINESS);
double angle = (i * 360.0) / (2*nSpikes);
xPoint[i] = (int) (ctrX + iRadius * Math.cos(Math.toRadians(angle - 90)));
yPoint[i] = (int) (ctrY + iRadius * Math.sin(Math.toRadians(angle - 90)));
}
//paint the star
Graphics2D g2 = (Graphics2D) bi.getGraphics();
g2.setColor(Color.blue);
g2.fillRect(0, 0, WIDTH, HEIGHT);
g2.setStroke(new BasicStroke(4.f));
g2.setColor(Color.yellow);
g2.drawPolyline(xPoint, yPoint, nPoints);
//insert control lines
g2.setStroke(new BasicStroke(1.f));
g2.setColor(Color.black);
for(int i = 0; i < nSpikes * 2; i++)
g2.drawLine(ctrX, ctrY, xPoint[i], yPoint[i]);
int w1 = RADIUS,
w2 = (int) (RADIUS * SPIKINESS);
g2.drawOval(ctrX - w1, ctrY - w1, w1 * 2, w1 * 2);
g2.drawOval(ctrX - w2, ctrY - w2, w2 * 2, w2 * 2);
}
}

Drawing bounding box around contours JavaCV?

I am wondering how to draw a bounding box around contours using JavaCV. I know the area of pixels and the center point. I also found a way to find the pixel width to find the distance. I feel a bounding box would be more accurate to find the pixel width to find the distance then what I am doing. Any help would be great or if you know another way to find the distance that would be great. Thanks...
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.opencv_core.CvMemStorage;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacpp.opencv_videoio.CvCapture;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
public class Webcam {
public static void main(String[] args) throws Exception {
CvCapture capture = opencv_videoio.cvCreateCameraCapture(0);
IplImage img1, imghsv, imgbin;
CvScalar minc = cvScalar(95,125,75,0), maxc = cvScalar(145,255,255,0);
CvSeq contour1 = new CvSeq(), contour2;
CvMemStorage storage = CvMemStorage.create();
CvMoments moments = new CvMoments(Loader.sizeof(CvMoments.class));
double areaMax = 1000, areaC = 0;
double m01, m10, m_area, focal, width, obj_width, obj_height;
double distance;
//focal is (pixel width * distance in inches) / object width
focal = 144.4;
//Real objects width in inches
obj_width = 3.5;
//Real objects height in inches
obj_height = 3.5;
int posX=0, posY=0;
int cRad = 100;
while(true)
{
img1 = opencv_videoio.cvQueryFrame(capture);
opencv_imgproc.cvSmooth(img1, img1, CV_MEDIAN, 13, 0, 0, 0);
imgbin = IplImage.create(cvGetSize(img1), 8, 1);
imghsv = IplImage.create(cvGetSize(img1), 8, 3);
if(img1 == null) break;
cvCvtColor(img1, imghsv, CV_BGR2HSV);
cvInRangeS(imghsv, minc, maxc, imgbin);
contour1 = new CvSeq();
areaMax = 1000;
cvFindContours(imgbin, storage, contour1, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_LINK_RUNS, cvPoint(0,0));
contour2 = contour1;
while(contour1 != null && !contour1.isNull())
{
areaC = cvContourArea(contour1, CV_WHOLE_SEQ, 1);
if(areaC > areaMax)
{
areaMax = areaC;
}
contour1 = contour1.h_next();
}
while(contour2 != null && !contour2.isNull())
{
areaC = cvContourArea(contour2, CV_WHOLE_SEQ, 1);
if(areaC < areaMax)
{
cvDrawContours(imgbin, contour2, CV_RGB(0,0,0),CV_RGB(0,0,0),0,CV_FILLED,8,cvPoint(0,0));
}
contour2 = contour2.h_next();
}
cvMoments(imgbin, moments, 1);
m10 = cvGetSpatialMoment(moments, 1, 0);
m01 = cvGetSpatialMoment(moments, 0, 1);
m_area = cvGetCentralMoment(moments, 0, 0);
posX = (int) (m10/m_area);
posY = (int) (m01/m_area);
if(posX > 0 && posY > 0)
{
cRad = (int) (100 / (5000/m_area));
cvCircle(img1, cvPoint(posX, posY), 5, cvScalar(0,255,0,0), 9, 0, 0);
}
//Change numbers after m_area to size of object
width = java.lang.Math.sqrt((m_area/(obj_height*obj_width)));
distance = (obj_width * focal) / width;
cvFlip(img1, img1, 1);
cvFlip(imgbin, imgbin , 1);
opencv_highgui.cvShowImage("Color",img1);
opencv_highgui.cvShowImage("CF",imgbin);
char c = (char) opencv_highgui.cvWaitKey(15);
if(c == 27) break;
if(c == 'q')
{
System.out.print("Width in pixels ");
System.out.println(width);
System.out.print("Distance in inches ");
System.out.println(distance);
}
}
}
}
This is what I have This is what I want . I am able to find all the blue contours and have the background turned black. I would just like to draw a bounding box around the blue pixels to help find the distance better to the object and to make sure we are tracking the right object.
If you want to draw a bouding box around a contour, you can do that with just using:
Rect rect = opencv_imgproc.boundingRect(contour);
opencv_imgproc.rectangle(src, rect, Scalar.GREEN);

Find circles image processing in OpenCV/JaVa

I'm using opencv and java to find circles on an image, I have the image below so far. I'm using Hough to find the circles with the code like this :
public static Vector<Mat> circles(Mat img){
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
long start_time = System.nanoTime();
Imgproc.resize(img, img, new Size(450,250));
Mat gray = new Mat();
Imgproc.cvtColor(img, gray, Imgproc.COLOR_BGR2GRAY);
Imgproc.blur(gray, gray, new Size(3, 3));
Mat edges = new Mat();
int lowThreshold = 40;
int ratio = 3;
Imgproc.Canny(gray, edges, lowThreshold, lowThreshold * ratio);
Mat circles = new Mat();
Vector<Mat> circlesList = new Vector<Mat>();
Imgproc.HoughCircles(edges, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 60, 200, 20, 30, 0 );
System.out.println("#rows " + circles.rows() + " #cols " + circles.cols());
double x = 0.0;
double y = 0.0;
int r = 0;
for( int i = 0; i < circles.rows(); i++ )
{
double[] data = circles.get(i, 0);
for(int j = 0 ; j < data.length ; j++){
x = data[0];
y = data[1];
r = (int) data[2];
}
Point center = new Point(x,y);
// circle center
Core.circle( img, center, 3, new Scalar(0,255,0), -1);
// circle outline
Core.circle( img, center, r, new Scalar(0,0,255), 1);
Imshow im1 = new Imshow("Hough");
im1.showImage(img);
Rect bbox = new Rect((int)Math.abs(x-r), (int)Math.abs(y-r), (int)2*r, (int)2*r);
Mat croped_image = new Mat(img, bbox);
Imgproc.resize(croped_image, croped_image, new Size(160,160));
circlesList.add(croped_image);
Imshow m2 = new Imshow("cropedImage");
m2.showImage(croped_image);
}
long end_time = System.nanoTime();
long duration = (end_time - start_time)/1000000; //divide by 1000000 to get milliseconds.
System.out.println("duration : " + duration * 0.001 + " s");
return circlesList;
}
BUT it always detects only one circle.
My Question is how I can detect all the circles in an image using java/OpenCV ?
Note:-
1- I'm using Mat called circles in HoughCircles function parameters , because the function requires a Mat in Java.
2- I'm using openCV 2.4.11 version.
The circles are saved in columns of the mat circles
try replacing for loop as:
for( int i = 0; i < circles.cols(); i++)
{
double[] data = circles.get(0,i);
...

Categories