например,

тоящее время я работаю над проектом, в котором я пытаюсь обнаружить несколько монет, лежащих на плоской поверхности (то есть столе). Монеты не перекрываются и не скрыты другими предметами. Но могут быть видны другие объекты, и условия освещения могут быть не идеальными ... По сути, вы снимаете свой стол, на котором есть монеты.

Таким образом, каждая точка должна быть видна как эллипс. Поскольку я не знаю положение камеры, форма эллипсов может варьироваться от круга (вид сверху) до плоских эллипсов в зависимости от угла, из которого сняты монеты.

Моя проблема в том, что я не уверен в том, как извлечь монеты и, наконец, наложить на них эллипсы (которые я ищу для дальнейших расчетов).

Сейчас я только что сделал первую попытку, установив пороговое значение в OpenCV, используя findContours () для получения контурных линий и подгонки эллипса. К сожалению, контурные линии редко дают мне форму монет (отражения, плохое освещение, ...), и этот способ также не является предпочтительным, так как я не хочу, чтобы пользователь устанавливал какой-либо порог.

Другая идея заключалась в том, чтобы использовать метод сопоставления шаблонов эллипса на этом изображении, но, поскольку я не знаю ни угла камеры, ни размера эллипсов, я не думаю, что это сработает хорошо ...

Поэтому я хотел спросить, может ли кто-нибудь сказать мне метод, который будет работать в моем случае ...

Есть ли быстрый способ извлечь три монеты из изображения? Расчеты должны быть выполнены в реальном времени на мобильных устройствах, и метод не должен быть слишком чувствительным для разных или меняющихся источников света или цвета фона.

Было бы замечательно, если бы кто-нибудь мог дать мне какие-либо советы о том, какой метод может работать для меня ...

 Dr. belisarius25 янв. 2011 г., 03:39
Почему вы хотите «подогнать эллипсы»? Не достаточно ли «найти эллипсы»?

Ответы на вопрос(3)

как я, но с использованием C ++:

После того, как вы использовалиfindContours чтобы найти контуры (как в ответе Миши выше), вы можете легко подогнать эллипсы, используя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]);
    }

как лучше всего решить вашу проблему. Что касается порогового значения, в частности, однако, вы можете использовать метод Оцу, который автоматически находит оптимальное пороговое значение на основе анализа гистограммы изображения. Используйте OpenCVпорог метод с параметромThresholdType равноTHRESH_OTSU.

Имейте в виду, однако, что метод Оцу хорошо работает только на изображениях с бимодальными гистограммами (например, изображения с яркими объектами на темном фоне).

Вы, наверное, видели это, но есть также метод дляпримерка эллипса вокруг набора 2D точек (например, связанный компонент).

РЕДАКТИРОВАТЬ: Метод Оцу, примененный к образцу изображения:

Изображение в градациях серого:

Результат применения метода Оцу:

 carnieri25 янв. 2011 г., 01:38
Вы не упоминали отслеживание раньше. Вам нужно отслеживать их, потому что они движутся или потому что камера движется? Я думаю, последнее. Попробуйте blobtrack_sample.cpp, который поставляется с OpenCV. Я получил хорошие результаты, отслеживая движущиеся транспортные средства, но в этом случае есть много хороших функций (поворотов) для отслеживания, с монетами это может быть сложнее.
 evident25 янв. 2011 г., 09:52
Отслеживание было просто идеей, если бы я использовал алгоритм водораздела. Пользователь сначала выбирает монеты, а затем они отслеживаются, так что я могу использовать алгоритм водораздела для сегментации монет каждый шаг. Но поскольку камера движется неуверенно, я сомневаюсь, что она будет хорошо работать с трекингом. Я все еще предпочел бы метод без отслеживания, если бы он работал хорошо ...
 evident25 янв. 2011 г., 00:55
Ах да, я слышал о методе Оцу. Это выглядит хорошо, но, как вы сказали, это будет работать только на двудольных гистограммах, и в большинстве случаев у меня этого не будет, поскольку в основном видны другие объекты. Я попробовал алгоритм водораздела на этой картинке, который работал нормально, но контрапункт тогда будет отслеживать монеты. Я могу попросить пользователя выбрать монеты и стол в начале, но затем он должен автоматически обнаружить монеты. Поэтому отслеживание отмеченных пятен с помощью фильтра Калмана или фильтра частиц, вероятно, не будет работать, поскольку движения могут быть неустойчивыми. У вас есть другие идеи или советы?
Решение Вопроса

реализующий традиционный подход (основанный на OpenCVDOCO):

#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);
    }
}

Учитывая двоичное изображение, предоставленное Карньери, это вывод:

./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

И это выходное изображение:

Что вы могли бы улучшить:

Обработка различных ориентаций эллипса (в настоящее время я предполагаю, что оси перпендикулярны / горизонтальны). Это было бы не сложно сделать, используя моменты изображения.Проверьте выпуклость объекта (посмотрите наcvConvexityDefects)

Ваш лучший способ отличить монеты от других предметов, вероятно, будет по форме. Я не могу думать о каких-либо других низкоуровневых функциях изображения (цвет явно отсутствует). Итак, я могу придумать два подхода:

Традиционное обнаружение объектов

Ваша первая задача - отделить объекты (монеты и не монеты) от фона. Метод Оцу, предложенный Карньери, будет хорошо работать здесь. Вы, кажется, беспокоитесь о том, что изображениядвураздельный но я не думаю, что это будет проблемой. До тех пор, пока видимое количество рабочих мест, вы гарантированно будете иметь один пик в гистограмме. И пока на столе есть пара визуально различимых предметов, вам гарантирован ваш второй пик.

распространяться ваше двоичное изображение пару раз, чтобы избавиться от шума, оставленного порогом. Монеты относительно большие, поэтому они должны пережить эту морфологическую операцию.

Сгруппируйте белые пиксели в объекты, используя увеличение области - просто итеративно соедините смежные пиксели переднего плана. В конце этой операции у вас будет список непересекающихся объектов, и вы будете знать, какие пиксели занимает каждый объект.

Из этой информации вы узнаете ширину и высоту объекта (из предыдущего шага). Итак, теперь вы можете оценить размер эллипса, который будет окружать объект, а затем посмотреть, насколько хорошо этот конкретный объект соответствует эллипсу. Может быть проще просто использовать соотношение ширины и высоты.

Кроме того, вы можете использоватьмоменты определить форму объекта более точно.

 evident25 янв. 2011 г., 10:06
спасибо за ваш код ... пример, который вы разместили, выглядит фантастически ... я попробую так ... оси только горизонтальные / вертикальные, если камера удерживается прямо ... но, возможно, я смогу получить это с телефона датчики ... спасибо!
 mpenkov25 янв. 2011 г., 10:10
Пожалуйста. Я удалил часть изображения из пирамиды, потому что думал, что обнаружение контура будет работать лучше. Но да, общая идея заключается в масштабировании в надежде превратить ваши эллипсы в круги, а затем в шаблонное совпадение. Не уверен насчет использования преобразования Хафа - это может занять больше времени, чем стоит.
 evident25 янв. 2011 г., 16:40
Правильно, они в основном должны быть выровнены ... так как монеты не слишком далеко друг от друга и камеры, я думаю, искажения перспективы не могут быть приемлемыми. Единственный контрапункт на данный момент - это когда камера наклонена, но я мог бы исправить это с помощью датчиков телефона. Спасибо всем!
 evident25 янв. 2011 г., 09:59
Это звучит действительно хорошо! Я собираюсь попробовать первый метод, чтобы увидеть, насколько хорошо он работает ... Если результатов недостаточно, я собираюсь попробовать другой подход ... так что под подбором шаблонов вы подразумеваете масштабирование изображения по вертикали и надеетесь, что эллипсы превратятся в круги, где я мог бы попробовать шаблон или даже преобразование Хафа на кругах ... спасибо!
 carnieri25 янв. 2011 г., 15:48
Фантастический ответ! Одна из замечательных особенностей компьютерного зрения заключается в том, что мы можем легко визуализировать результаты, как показывает ваше выходное изображение. Одно: я согласен с очевидным, что ориентация эллипсов всегда будет примерно одинаковой, поскольку они находятся на одной плоской поверхности. Тем не менее, искажения перспективы могут быть значительными в зависимости от расстояния между камерой и монетами.

Ваш ответ на вопрос