检测图像上的硬币(和拟合椭圆) [英] Detection of coins (and fit ellipses) on an image

查看:151
本文介绍了检测图像上的硬币(和拟合椭圆)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开展一个项目,我正试图检测一些平躺在平面上的硬币(即桌子)。硬币不重叠,不会被其他物体隐藏。但可能有其他物体可见,照明条件可能不完美......基本上考虑自己拍摄你的桌子上有一些硬币。



所以每个点应该作为椭圆可见。由于我不知道相机的位置,椭圆的形状可能会有所不同,从圆圈(从顶部看)到平面椭圆,取决于硬币拍摄的角度。



我的问题是我不知道如何提取硬币并最终将椭圆放在它们上面(我正在寻找进一步的计算)。



现在我刚刚通过在OpenCV中设置阈值进行了第一次尝试,使用findContours()来获取轮廓线并拟合椭圆。不幸的是,轮廓线很少给我硬币的形状(反射,光线不好......),这种方式也不是首选,因为我不希望用户设置任何阈值。



另一个想法是在该图像上使用椭圆的模板匹配方法,但由于我不知道相机的角度和椭圆的大小,我认为这不会很好。 ..



所以我想问一下是否有人可以告诉我一个适用于我的方法......



有没有快速的方法从图像中提取三个硬币?计算应该在移动设备上实时进行,并且该方法对于不同或变化的灯光或背景颜色不应过于敏感。



如果有人能给我任何关于哪种方法可以为我工作的提示,那就太好了...

解决方案

这里有一些C99来源实现了传统方法(基于OpenCV 您的二进制图像几次以消除阈值处理留下的噪音。硬币相对较大,因此它们应该能够在这种形态运算中存活下来。



使用区域增长将白色像素分组为对象 - 只需迭代连接相邻的前景像素。在此操作结束时,您将获得一个不相交的对象列表,您将知道每个对象占用的像素。



从这些信息中,您将知道宽度和对象的高度(来自上一步)。因此,现在您可以估计围绕对象的椭圆的大小,然后查看此特定对象与椭圆的匹配程度。使用宽高比可能更容易。



或者,您可以使用片刻以更精确的方式确定对象的形状。


I am currently working on a project where I am trying to detect a few coins lying on a flat surface (i.e. a desk). The coins do not overlap and are not hidden by other objects. But there might be other objects visible and the lighting conditions may not be perfect... Basically consider yourself filming your desk which has some coins on it.

So each point should be visible as an Ellipse. Since I don't know the position of the camera the shape of the ellipses may vary, from circle (view from top) to flat ellipses depending on the angle the coins are filmed from.

My problem is that I am not sure on how to extract the coins and finally fit ellipses over them (which I am looking for to do further calculations).

For now I have just made a first attempt by setting a threshold value in OpenCV, using findContours() to get the contour lines and fitting an ellipse. Unfortunately the contour lines only rarely give me the shape of the coins (reflections, bad lighting, ...) and this way is also not preferred since I dont want the user to set any threshold.

Another idea was to use a template matching method of an ellipse on that image, but since I don't know the angle of the camera nor the size of the ellipses I don't think this would work well...

So I wanted to ask if anybody could tell me a method that would work in my case...

Is there a fast way to extract the three coins from the image? The calculations should be made in realtime on mobile devices and the method should not be too sensitive for different or changing lights or the color of the background.

Would be great if anybody could give me any tips on which method could work for me...

解决方案

Here's some C99 source implementing the traditional approach (based on OpenCV doco):

#include "cv.h"
#include "highgui.h"

#include <stdio.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

//
// We need this to be high enough to get rid of things that are too small too
// have a definite shape.  Otherwise, they will end up as ellipse false positives.
//
#define MIN_AREA 100.00    
//
// One way to tell if an object is an ellipse is to look at the relationship
// of its area to its dimensions.  If its actual occupied area can be estimated
// using the well-known area formula Area = PI*A*B, then it has a good chance of
// being an ellipse.
//
// This value is the maximum permissible error between actual and estimated area.
//
#define MAX_TOL  100.00

int main( int argc, char** argv )
{
    IplImage* src;
    // the first command line parameter must be file name of binary (black-n-white) image
    if( argc == 2 && (src=cvLoadImage(argv[1], 0))!= 0)
    {
        IplImage* dst  = cvCreateImage( cvGetSize(src), 8, 3 );
        CvMemStorage* storage = cvCreateMemStorage(0);
        CvSeq* contour = 0;    
        cvThreshold( src, src, 1, 255, CV_THRESH_BINARY );
        //
        // Invert the image such that white is foreground, black is background.
        // Dilate to get rid of noise.
        //
        cvXorS(src, cvScalar(255, 0, 0, 0), src, NULL);
        cvDilate(src, src, NULL, 2);    
        cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
        cvZero( dst );

        for( ; contour != 0; contour = contour->h_next )
        {
            double actual_area = fabs(cvContourArea(contour, CV_WHOLE_SEQ, 0));
            if (actual_area < MIN_AREA)
                continue;

            //
            // FIXME:
            // Assuming the axes of the ellipse are vertical/perpendicular.
            //
            CvRect rect = ((CvContour *)contour)->rect;
            int A = rect.width / 2; 
            int B = rect.height / 2;
            double estimated_area = M_PI * A * B;
            double error = fabs(actual_area - estimated_area);    
            if (error > MAX_TOL)
                continue;    
            printf
            (
                 "center x: %d y: %d A: %d B: %d\n",
                 rect.x + A,
                 rect.y + B,
                 A,
                 B
            );

            CvScalar color = CV_RGB( rand() % 255, rand() % 255, rand() % 255 );
            cvDrawContours( dst, contour, color, color, -1, CV_FILLED, 8, cvPoint(0,0));
        }

        cvSaveImage("coins.png", dst, 0);
    }
}

Given the binary image that Carnieri provided, this is the output:

./opencv-contour.out coin-ohtsu.pbm
center x: 291 y: 328 A: 54 B: 42
center x: 286 y: 225 A: 46 B: 32
center x: 471 y: 221 A: 48 B: 33
center x: 140 y: 210 A: 42 B: 28
center x: 419 y: 116 A: 32 B: 19

And this is the output image:

What you could improve on:

  • Handle different ellipse orientations (currently, I assume the axes are perpendicular/horizontal). This would not be hard to do using image moments.
  • Check for object convexity (have a look at cvConvexityDefects)

Your best way of distinguishing coins from other objects is probably going to be by shape. I can't think of any other low-level image features (color is obviously out). So, I can think of two approaches:

Traditional object detection

Your first task is to separate the objects (coins and non-coins) from the background. Ohtsu's method, as suggested by Carnieri, will work well here. You seem to worry about the images being bipartite but I don't think this will be a problem. As long as there is a significant amount of desk visible, you're guaranteed to have one peak in your histogram. And as long as there are a couple of visually distinguishable objects on the desk, you are guaranteed your second peak.

Dilate your binary image a couple of times to get rid of noise left by thresholding. The coins are relatively big so they should survive this morphological operation.

Group the white pixels into objects using region growing -- just iteratively connect adjacent foreground pixels. At the end of this operation you will have a list of disjoint objects, and you will know which pixels each object occupies.

From this information, you will know the width and the height of the object (from the previous step). So, now you can estimate the size of the ellipse that would surround the object, and then see how well this particular object matches the ellipse. It may be easier just to use width vs height ratio.

Alternatively, you can then use moments to determine the shape of the object in a more precise way.

这篇关于检测图像上的硬币(和拟合椭圆)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆