我正在制作一个Android应用程序,该应用程序在进行台球游戏的图像并检测各种球的位置。该图像是从某人的电话中拍摄的,因此,我当然没有这张桌子的完美俯 View 。现在,我正在使用houghcircles来找到球,并且做得不错,但是似乎到处都错过了一些球,然后出现了误报。
我现在最大的问题是,如何减少桌子外发现的误报?我正在使用ROI来切除图像的顶部,因为它主要是浪费的空间,但是我不能将其缩小,或者由于它是梯形形状而冒着切掉桌子的部分的风险。我目前的想法是将用户在将图片拍摄到图像上方时看到的指南覆盖,但是问题是我不知道他们的相机的分辨率是多少,因此覆盖可能会覆盖错了点。理想情况下,我认为我想使用辅助线,但是当我尝试使用它时,我的应用程序由于我认为内存不足而崩溃了。有任何想法吗?
这是我得到的结果的链接:
http://graphiquest.com/cvhoughcircles.html
这是我的代码:
IplImage img = cvLoadImage("/sdcard/DCIM/test/picture"+i+".jpg",1);
IplImage gray = opencv_core.cvCreateImage( opencv_core.cvSize( img.width(), img.height() ), opencv_core.IPL_DEPTH_8U, 1);
cvCvtColor(img, gray, opencv_imgproc.CV_RGB2GRAY );
cvSetImageROI(gray, cvRect(0, (int)(img.height()*.15), (int)img.width(), (int)(img.height()-(img.height()*.20))));
cvSmooth(gray,gray,opencv_imgproc.CV_GAUSSIAN,9,9,2,2);
Pointer circles = CvMemStorage.create();
CvSeq seq = cvHoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2.5d, (double)gray.height()/30, 70d, 100d, 0, 80);
for(int j=0; j<seq.total(); j++){
CvPoint3D32f point = new CvPoint3D32f(cvGetSeqElem(seq, j));
float xyr[] = {point.x(),point.y(),point.z()};
CvPoint center = new CvPoint(Math.round(xyr[0]), Math.round(xyr[1]));
int radius = Math.round(xyr[2]);
cvCircle(gray, center, 3, CvScalar.GREEN, -1, 8, 0);
cvCircle(gray, center, radius, CvScalar.BLUE, 3, 8, 0);
}
String path = "/sdcard/DCIM/test/";
File photo=new File(path, "picture"+i+"_2.jpg");
if (photo.exists())
{
photo.delete();
}
cvSaveImage("/sdcard/DCIM/test/picture"+i+"_2.jpg", gray);
最佳答案
您可以应用一些非常有用的约束。除了制作矩形区域外,您还应使用台球桌的实际梯形形状遮盖结果。使用图像的颜色信息查找台球桌区域。您知道台球桌是纯色的。它不一定是绿色的-您可以在HSV颜色空间中使用一些histogram技术来查找图像中最流行的颜色,也许偏向中心的像素。很可能检测到台球桌的颜色。选择与该颜色匹配的像素,执行形态学操作以消除噪声,然后可以将蒙版视为轮廓,并找到其convexHull。填充船体以消除池球造成的孔。
到目前为止,我所说的内容应该提出与霍夫圈子不同的方法。由于台球没有被均匀照亮,霍夫圆圈可能无法很好地工作。因此,查找台球的另一种方法是从凸台球壳中减去台球桌的颜色蒙版。您将剩下桌子上被球遮盖的区域。
关于android - 使用OpenCV检测台球,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8162234/