What is the translation of this code to OpenCV Java? - java

This code is OpenCV c++:
lines = cvHoughCircles(frame2, storage, CV_HOUGH_GRADIENT, 1, 50, 300, 60, 10, 600);
for (int i = 0; i < lines.total(); i++) {
//Would like the code to go here
CvPoint2D32f point = new CvPoint2D32f(cvGetSeqElem(lines, i));
cvCircle(src, cvPoint((int)point.x(), (int)point.y()), 3, CvScalar.WHITE, -1, 8, 0);
Point p = new Point((int)point.x(), (int)point.y());
points.add(p);
}
What is the correspondent in the new Java Api? I cannot get CvPoint2D32f, cvGetSeqElem and CV_AA. I found that existed in JavaCV but cannot find them in OpenCV Java api.
Thanks
EDIT:
I've changed my code and now I have:
MatOfPoint3 circles = new MatOfPoint3();
Imgproc.HoughCircles(image, circles, Imgproc.CV_HOUGH_GRADIENT,2, image.rows()/4,200,100,0,0);
for(Point3 circle : circles.toArray()){
Point center = new Point(circle.x, circle.y);
int radius = (int) Math.round(circle.z);
Core.circle(image, center, radius, new Scalar(0,255,0), 6, 8, 0);
}
However I got an error at for(Point3 circle : circles.toArray()):
Exception in thread "main" java.lang.UnsupportedOperationException: Mat data type is not compatible: 21
at org.opencv.core.Mat.get(Mat.java:2581)
at org.opencv.core.MatOfPoint3.toArray(MatOfPoint3.java:64)
at org.opencv.core.MatOfPoint3.toList(MatOfPoint3.java:76)
at main.java.DetectFaceDemo.run(HelloOpenCV.java:60)
at main.java.HelloOpenCV.main(HelloOpenCV.java:83)
Any thoughts on this? Thanks
EDIT 2:
The solution to last edit problem resides in
MatOfPoint3 circles = new MatOfPoint3();
It must be
MatOfPoint3f circles = new MatOfPoint3f();

Use Class Point3. Template class for 3D points specified by its coordinates x, y and z. An instance of the class is interchangeable with the C structure CvPoint2D32f. Similarly to Point_, the coordinates of 3D points can be converted to another type. The vector arithmetic and comparison operations are also supported.

Related

Translate C++ code to Java with Mat object

I have working code in Visual Studio with C ++ on a watershed algorithm and I need to pass it to Android Studio. I have added the OpenCV library to the app and the simple operations work. Now, my problem is that when I want to pass the code to Java there is a specific line type that I don't know how to pass. The part of the code is:
cv::Mat markers(original.size(), CV_8U, cv::Scalar(-1));
//Rect(topleftcornerX, topleftcornerY, width, height);
//top rectangle
markers(Rect(0, 0, original.cols, 5)) = Scalar::all(1);
//bottom rectangle
markers(Rect(0, original.rows - 5, original.cols, 5)) = Scalar::all(1);
//left rectangle
markers(Rect(0, 0, 5, original.rows)) = Scalar::all(1);
//right rectangle
markers(Rect(original.cols - 5, 0, 5, original.rows)) = Scalar::all(1);
What would be the creation of the object would be something like this:
Mat markers = new Mat(rgba.size(), CvType.CV_8UC3, new Scalar(-1));
But the rest of the lines do not know how they would be transformed. Help please?
markers.submat(0, 0, original.cols, 5).setTo(new Scalar(1, 1, 1));
or
Imgproc.rectangle (
markers,
new Point(0, 0),
new Point( original.cols, 5),
new Scalar(1, 1, 1),
-1
);

Draw directed edge of an automata in Java

I am required to write something similar to graphviz. I have already managed to draw the nodes so that they do not overlap and to connect their center with a quadratic Bezier curve, but I am facing the following problem with the directionality of a curved edge:
As you can see, the yellow little triangle is not quite nice. My code is the following:
g.setColor(Color.RED);
ArrowGraph arrow = graph.getArrows().get(0);
int x = (int)(arrow.getP1().getX() + arrow.getP2().getX()) / 2;
int y = (int)(arrow.getP1().getY() + arrow.getP2().getY()) / 2 + 50;
QuadCurve2D.Double curve = new QuadCurve2D.Double(arrow.getP1().getX() - 20, arrow.getP1().getY() - 20, x, y, arrow.getP2().getX() - 20, arrow.getP2().getY() - 20);
((Graphics2D)g).draw(curve);
int[] xPoints = new int[] {(int)arrow.getP2().getX() - 20, (int)arrow.getP2().getX() - 15, (int)arrow.getP2().getX() - 25};
int[] yPoints = new int[] {(int)arrow.getP2().getY() - 20, (int)arrow.getP2().getY() - 10, (int)arrow.getP2().getY() - 10};
g.setColor(Color.YELLOW);
g.fillPolygon(xPoints, yPoints, 3);
The coordinates that I know: the start and end point and the control point of the curve. The start and the end points are basically the centers of the nodes.
I would like to somehow adjust the triangle to the curve, so it's on the end of it (preferably at border of the node). Any idea how I could do that?
You can use FlatteningPathIterator passing your curve and get the last segment (last line on the path in fact).
The use the line to to build the arrow triangle.

Merging two polygons in Java

Is there a clean Java method for merging the points of two given overlapping polygons into one polygon?
What you want is a Convex Hull Algorithm it will take a set of points and return a minimal set of points that encloses the original points. This can be done in n.log n time.
The Area class supports addition of closed polygons.
Convex Hull is different from adding. Adding means making a polygon that looks like the two polygons overlapped which is not necessarily convex.
You can use JTS (Java Topology Suite) for that.
Create your Polygon objects
Use the union method which will return a Set of all points from both polygons
Simple code example:
Given Polygon 1 (as WKT): POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
Given Polygon 2 (as WKT): POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))
// create polygons
Polygon p1 = new GeometryFactory().createPolygon(new Coordinate[]{new Coordinate(0, 0), new Coordinate(0,10), new Coordinate(10,10), new Coordinate(10,0), new Coordinate(0,0)});
Polygon p2 = new GeometryFactory().createPolygon(new Coordinate[]{new Coordinate(5,5), new Coordinate(15,5), new Coordinate(15,15), new Coordinate(5,15), new Coordinate(5,5)});
// calculate union
Geometry union = p1.union(p2);
// print as WKT
System.out.println(union.toText());
The result is a new polygon:
POLYGON ((0 0, 0 10, 5 10, 5 15, 15 15, 15 5, 10 5, 10 0, 0 0))
Using the algorithm #Charles Keepax provided, you can do something like this:
public static Polygon mergePolygons(Polygon a, Polygon b) {
// create arrays for border of each polygon
Point[] a_pts = new Point[a.npoints];
Point[] b_pts = new Point[b.npoints];
// fill them in an array of Points instead of separate coords.
Arrays.setAll(a_pts, i -> new Point(a.xpoints[i], a.ypoints[i]));
Arrays.setAll(b_pts, i -> new Point(b.xpoints[i], b.ypoints[i]));
// first merge 2 arrays into 1
Point[] all_pts = (Point[]) mergeArrays(a_pts, b_pts);
// apply Convex Hull on resulting array
convexHull(all_pts, all_pts.length);
// separate x and y coordinates back
int[] x_pts = new int[all_pts.length];
int[] y_pts = new int[all_pts.length];
Arrays.setAll(x_pts, i -> all_pts[i].x);
Arrays.setAll(y_pts, i -> all_pts[i].y);
// return polygon object using those coordinates
return new Polygon(x_pts, y_pts, all_pts.length);
}
But of course solution by #Lars is more practical, this is how you could do it in a naive way.

Please can some one help on convert opencv code in to javacv?

I have found some code which recognize circles in particular image and I was able to convert 90% of that code it in to javacv. But unfortunately I couldn't able to convert following lines in to javacv. So please can some one help me to convert this lines into javacv ?
CvSeq circles = cvHoughCircles(gry, mem, CV_HOUGH_GRADIENT, 1, 40.0, 100, 100,0,0);
cvCvtColor(canny, rgbcanny, CV_GRAY2BGR);
for (int i = 0; i < circles->total; i++)
{
// round the floats to an int
float* p = (float*)cvGetSeqElem(circles, i);
cv::Point center(cvRound(p[0]), cvRound(p[1]));
int radius = cvRound(p[2]);
// draw the circle center
cvCircle(img, center, 3, CV_RGB(0,255,0), -1, 8, 0 );
// draw the circle outline
cvCircle(img, center, radius+1, CV_RGB(0,0,255), 2, 8, 0 );
printf("x: %d y: %d r: %d\n",center.x,center.y, radius);
}
I just need to know how to convert 5 code lines which inside the for loop. Please be kind enough to share your experience. Thanks.
Well, I'm not going to convert that code for you (I don't know JavaCV) but here's some useful links for you:
Hints for Converting OpenCV C/C++ code to JavaCV - this is the very first thing you should read.
JavaCV source code - in this archive there's file samples/HoughLines.java. It's very similar to HoughCircles.java wich was deleted from repo.
JavaCV examples - this archive contains file OpenCV2_Cookbook/src/opencv2_cookbook/chapter07/ex4HoughCircles.scala. And here's some part of code from this file:
// Draw lines on the canny contour image
val colorDst = cvCreateImage(cvGetSize(src), src.depth(), 3)
cvCvtColor(src, colorDst, CV_GRAY2BGR)
for (i <- 0 until circles.total) {
val point = new CvPoint3D32f(cvGetSeqElem(circles, i))
val center = cvPointFrom32f(new CvPoint2D32f(point.x, point.y))
val radius = math.round(point.z)
cvCircle(colorDst, center, radius, CV_RGB(255, 0, 0), 1, CV_AA, 0)
print(point)
}
show(colorDst, "Hough Circles")
This is exactly what you're looking for.

Trying to get the centre of a circle with opencv

I'm trying to detect the center of a circle. I try to do this with cvHoughCircle. But I can't seem to get it working properly .
The only thing that can vary is the size of the circle.
I try detecting the circle by doing :
circle = cvHoughCircles(imgThreshold, storage, CV_HOUGH_GRADIENT, 1,
(double)imgThreshold.height()/20, 200, 20, 0, 0);
imgThreshold is the b/w image you can see here. The resolution of the image is in fact 1280*1024.
Can anyone tell me what I am doing wrong.
Instead of using cvHoughCircle it is possible to solve this problem with a bit of math:
CvMoments moments = new CvMoments();
cvMoments(imgThreshold, moments, 1);
double moment10 = cvGetSpatialMoment(moments, 1, 0);
double moment01 = cvGetSpatialMoment(moments,0,1);
double area = cvGetCentralMoment(moments, 0, 0);
int posX = 0;
int posY = 0;
int lastX = posX;
int lastY = posY;
posX = (int) (moment10/area);
posY = (int) (moment01/area);
cvCircle(iplRgbImage, new CvPoint(posX,posY), 3, CvScalar.GREEN, -1, 8, 0);
source = http://aishack.in/tutorials/tracking-colored-objects-in-opencv/
If the circle is complete and filled and not occluded by other shapes, you can use findContours() and then find the center of the contour.
use cvBlob
https://code.google.com/p/cvblob/
Concerning Hough transform it can detect circles by identifying pixels that belongs to a circle periphery. More precisely given a binary (thresholded) image containing ie white pixels along a cyclic path, the hough circle transform will detect the circle. So the image to feed the algorithm should be binary and thresholded but in your example must be the thresholded example of an edge filter (ex Sobel) rather than a solid filled circle.
I can not tell a right way of "fitting" a circle on the above image, but the centroid of the blob extracted with connected components is a good and fast way to go.

Categories

Resources