Image 在图像上检测硬币(和拟合椭圆)
我目前正在一个项目中工作,我试图发现一些硬币躺在一个平面上(例如桌子上)。硬币不会重叠,也不会被其他物体隐藏。但可能还有其他可见的物体,而且照明条件可能并不完美。。。基本上,考虑你自己在你的桌子上拍摄一些硬币。 所以每个点都应该是可见的椭圆。由于我不知道相机的位置,椭圆的形状可能会有所不同,从圆形(从顶部观看)到扁平椭圆,这取决于硬币拍摄的角度 我的问题是,我不知道如何提取硬币,并最终在其上拟合椭圆(我正在寻找做进一步的计算) 现在,我刚刚做了第一次尝试,在OpenCV中设置了一个阈值,使用findContours()获得轮廓线并拟合椭圆。不幸的是,轮廓线很少给我硬币的形状(反射、光线不好等等),这种方式也不是首选,因为我不希望用户设置任何阈值 另一个想法是在该图像上使用椭圆的模板匹配方法,但由于我不知道相机的角度,也不知道椭圆的大小,我认为这不会很好地工作 所以我想问是否有人能告诉我一种适合我的方法 有没有快速的方法从图像中提取三枚硬币?应在移动设备上实时进行计算,并且该方法对于不同或变化的灯光或背景颜色不应太敏感。Image 在图像上检测硬币(和拟合椭圆),image,image-processing,opencv,image-recognition,Image,Image Processing,Opencv,Image Recognition,我目前正在一个项目中工作,我试图发现一些硬币躺在一个平面上(例如桌子上)。硬币不会重叠,也不会被其他物体隐藏。但可能还有其他可见的物体,而且照明条件可能并不完美。。。基本上,考虑你自己在你的桌子上拍摄一些硬币。 所以每个点都应该是可见的椭圆。由于我不知道相机的位置,椭圆的形状可能会有所不同,从圆形(从顶部观看)到扁平椭圆,这取决于硬币拍摄的角度 我的问题是,我不知道如何提取硬币,并最终在其上拟合椭圆(我正在寻找做进一步的计算) 现在,我刚刚做了第一次尝试,在OpenCV中设置了一个阈值,使用fi
如果有人能告诉我哪种方法对我有效,那就太好了。我不知道解决你问题的最佳方法是什么。但是,关于阈值,您可以使用Otsu的方法,该方法根据图像直方图的分析自动找到最佳阈值。使用OpenCV的方法,参数
ThresholdType
等于THRESH_OTSU
不过,请注意,大津的方法仅适用于具有双峰直方图的图像(例如,在黑暗背景下具有明亮物体的图像)
您可能已经看到了这一点,但也有一种方法用于处理一组二维点(例如,连接的组件)
编辑:应用于样本图像的大津方法:
灰度图像:
应用大津方法的结果:
以下是一些实现传统方法(基于OpenCV)的C99源代码: 这是输出图像: 您可以改进的方面:
- 处理不同的椭圆方向(目前,我假设轴是垂直/水平的)。使用图像瞬间,这并不难做到
- 检查对象凸度(查看
)cvconverxitydefects
或者,您可以使用以更精确的方式确定对象的形状。如果将来有人像我一样出现此问题,但使用C++: 使用
findContours
查找轮廓后(如上面Misha的回答),您可以使用fitEllipse
轻松拟合椭圆,例如
vector<vector<Point> > contours;
findContours(img, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
RotatedRect rotRecs[contours.size()];
for (int i = 0; i < contours.size(); i++) {
rotRecs[i] = fitEllipse(contours[i]);
}
矢量轮廓;
查找轮廓(img、等高线、等高线树、等高线链近似、点(0,0));
RotatedRect rotRecs[轮廓.size()];
对于(int i=0;i
啊,对了,我听说过大津的方法。这看起来不错,但就像你说的,它只适用于二分直方图,在大多数情况下,我不会这样做,因为大部分其他对象都是可见的。我在这张照片上尝试了分水岭算法,效果很好,但对位法是跟踪硬币。我可以让用户在开始时选择硬币和桌子,但之后它会自动检测硬币。因此,用卡尔曼滤波器或粒子滤波器跟踪标记点可能不起作用,因为运动可能是不稳定的。你还有其他想法或建议吗?你以前没有提到过跟踪。你需要跟踪他们是因为他们在移动还是因为相机在移动?我猜是后者。请尝试OpenCV附带的blobtrack_sample.cpp。我在跟踪移动的车辆时得到了很好的效果,但在这种情况下,有很多很好的特征(拐角)需要跟踪,使用硬币可能会更困难。如果我使用
vector<vector<Point> > contours;
findContours(img, contours, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
RotatedRect rotRecs[contours.size()];
for (int i = 0; i < contours.size(); i++) {
rotRecs[i] = fitEllipse(contours[i]);
}