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:
Imgproc.medianBlur(result, result, 3);
Imgproc.medianBlur(result, result, 3);
Imgproc.medianBlur(result, result, 3);
Mat circles = new Mat();
Imgproc.HoughCircles(result, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 1, 200, 100, 30, 40);
System.out.println(circles.dump());
But I get an empty Mat for result with and without the blur.
How should I fix this code?
EDIT :
Hi guys!
Thanks to you I have this picture now. I'm using these parameters:
Imgproc.HoughCircles(result, circles, Imgproc.CV_HOUGH_GRADIENT, 1, 20, 50, 10, 10, 40);
I'm still using the medianBlur before the detection.
The only question left is why does it detect these small circles? I've attached the result of the canny detection, I think the circles are pretty seeable .
First of all, the circles structure should not be cv::Mat but should be std::vector<cv::Vec3f>; I think that is why you aren't getting any results.. Please refer to the documentation on the HoughCircles for details..
Playing around with the values for 5 minutes, I have this starting point for you:
The parameters I used are,
cv::medianBlur(test_Circle, test_Circle, 7);
std::vector<cv::Vec3f> circles; // <- not that "circles" is not cv::Mat
cv::HoughCircles(test_Circle, circles, CV_HOUGH_GRADIENT, 1, 1, 300, 10, 10, 50);
You can get much more defined result after you played around with the values a bit.
PS - Since I am a C++ user, please excuse me for putting all my structures in that format. You can easily extend the logic to Java. :)
Are you sure you are providing radius and not diameter? Try wider range of radiuses (10-100 for example).
Using OpenCV to cheat in Zuma? :)
I've tested my code, it writtent in C# (i think java is the same) and get the result:1
You can find my code in HoughAlgorithm.cs class
My demo Project Here
//DP_Resolution: 1
//MinDistance :32
//CannyThreshold: 10
//AccuThreshold: 10
//MinRadius: 13
//MaxRadius: 20
public static CvSeq DetectCircles(IplImage pImage, CamEnum _camName)
{
try
{
CvMemStorage memStorage = cvlib.CvCreateMemStorage(0);
return cvlib.CvHoughCircles(ref pImage, memStorage.ptr, 3, 1, 32, 10, 10, 13, 20);
}
catch
{
throw;
}
}
http://i.stack.imgur.com/pUqbh.png
Related
here is what I have now
//Thresholding
Mat mat2 = mat.clone(); //mat is origin picture
Imgproc.cvtColor(mat2, mat2, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(mat2, mat2, -1, 255, Imgproc.THRESH_BINARY+ Imgproc.THRESH_OTSU);
//Erosion and Dilation
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*dilation_size + 1, 2*dilation_size+1));
Imgproc.dilate(mat2, mat2, element);
element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*erosion_size + 1, 2*erosion_size+1));
Imgproc.erode(mat2, mat2, element);
I make a program to detect the rectangle block. After thresholding, the rectangle blocks become weird.
Is there have anyway to make a good effect of threshold or fix it?
Update
cut from Origin image, dpi is low.
After Threadholding
I would try first to apply some blur to get rid of noise and test the threshold again if still does not work there is an OpenCV page with examples how to denoise.
You should try to sharpen your image. There are many many methods for this, but I don't know which ones are implemented in OpenCV.
For example, using GIMP's unsharp mask tool (parameters 300, 5, 0), I get a result which may be easier to threshold:
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.
I am using Androidplot (v0.5.0) and I want segments of my plotted series to be different colours.
I think I need to use RectRegion but the region never shows.
XYSeries series = new SimpleXYSeries(timestamps, item.getValues(), "");
LineAndPointFormatter seriesFmt = new LineAndPointFormatter(
Color.rgb(0, 200, 0),
Color.rgb(0, 100, 0),
Color.rgb(150, 190, 150));
XYRegionFormatter regionFmter = new XYRegionFormatter(Color.RED);
RectRegion region = new RectRegion(0, 10, 0, 10);
seriesFmt.addRegion(region, regionFmter);
I cant find the doco anymore for this but I can find old images from the old tutorials of what I was trying to achieve.
http://androidplot.com/w/images/thumb/1/12/RectRegions_final.jpg/398px-RectRegions_final.jpg
Here's a link to the full source code that generated the graphic you posted - hopefully that provides answers you are looking for :)
https://androidplot.jira.com/source/browse/ANDROIDPLOT/trunk/Examples/DemoApp/src/com/androidplot/demos/XYRegionExampleActivity.java?hb=true
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.
As the title says I wonder how I can make my images to perspective view. Here's an image showing how they manage to do this in photoshop:
http://netlumination.com/blog/creating-perspective-and-a-mirror-image-in-photoshop
Is it possible to do something like this in android?
Yes.
Have a look at this page http://www.inter-fuser.com/2009/12/android-reflections-with-bitmaps.html.
You can then apply an AffineTransform (at least in AWT, but Android should have something similar, too) using a matrix to distort/skew the image.
Edit: see http://www.jhlabs.com/ip/filters/index.html for an implementation of a PerspectiveFilter.
Note that you could probably also use openGL to achieve a similar effect. See http://developer.android.com/reference/android/opengl/GLU.html and http://developer.android.com/reference/android/opengl/GLSurfaceView.html
This works pretty well for me, for values of rotation between 0 and 60:
Matrix imageMatrix = new Matrix();
float[] srcPoints = {
0, 0,
0, 200,
200, 200,
200, 0};
float[] destPoints = {
rotation, rotation/2f,
rotation, 200 - rotation/2f,
200 - rotation, 200,
200 - rotation, 0};
imageMatrix.setPolyToPoly(srcPoints, 0, destPoints, 0, 4);