roboforum.ru

Технический форум по робототехнике.

Нахождение части изображения на другом изображении

Нахождение части изображения на другом изображении

Zeus » 15 авг 2012, 14:38

Имеем две камеры. Первая камера наводится вручную, Вторая сервоприводами вверх-вниз, влево-вправо.
Камеры стоят на одной оси - типа стереозрение.
Первую камеру выставляем вручную.
Вторая камера должна повернуться туда-же куда смотрит первая, естественно с определенной долей погрешности.

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

Определение и выделение объектов на изображении не интересует.

Как это сделать? Какие методы использовать?
Имеется ввиду использование OpenCV

Re: Нахождение части изображения на другом изображении

Romikgy » 15 авг 2012, 15:12

не в курсе как в OpenCV , а вообще корреляцией ... сорри если не в тему...

Re: Нахождение части изображения на другом изображении

Zeus » 15 авг 2012, 15:47

Почему не в тему?! как раз в тему.
Только на сколько я понимаю корреляция всего изображения будет перебором делаться под размер образца образец, а это наверное будет долго.

Может сперва по цветам искать, а потом корреляцию?
или есть что пошустрее?

Re: Нахождение части изображения на другом изображении

Romikgy » 15 авг 2012, 16:20

тогда могу предложить поиск в 2 этапа :
1. берем малый квадрат инфы , допустим 16х16 с верхнего левого угла , и исчим корреляцию по всей картинке , при совпадении более 50-90 % второй шаг
2. корреляция всего участка 100х100 от последней координаты совпадения...

Re: Нахождение части изображения на другом изображении

Madf » 15 авг 2012, 16:48

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

Re: Нахождение части изображения на другом изображении

Romikgy » 15 авг 2012, 16:57

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

Re: Нахождение части изображения на другом изображении

Angel71 » 15 авг 2012, 20:14

попиксельно это вариант, но имхо крайне неудачный. "смотреть" какмеры будут с разных точек, спору нет. а то, что без поворота (прям пиксель в пиксель по горизонтали) хоть на небольшой угол это сомнительно. вообще более точно и быстро это сначала искать особенности и затем уже по ним сравнивать 2 изображения. маштабирование и повороты в 2х или 3х мерном пространстве до разумной степени вам не страшны. порылся, в доке opencv поиск ответов можно начать со страницы feature detection. вроде наиболее популярен surf. примеров более чем завались. https://code.ros.org/trac/opencv/browser/trunk/opencv/samples/c/find_obj.cpp?rev=3110

Re: Нахождение части изображения на другом изображении

Zeus » 21 авг 2012, 17:44

Начал пробовать c корреляцией и ее нормированием, функция opencv - cvMatchTemplate

Работает когда как, результат зависит от всего...

Код: Выделить всёРазвернуть
#include <stdafx.h>
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

CvCapture *capture;
IplImage *original, *sight, *frame, *result;

bool flag; // while (flag){;}
char c; //c = cvWaitKey(33);

int main(int argc, char* argv[])
{      // получаем любую подключенную камеру
      capture = cvCreateCameraCapture(-1);
      assert( capture != 0 );

      // получаем кадр
      original = cvQueryFrame (capture);
      // выводим в консоль информацию
      printf( "[i] Camera\n");
        printf( "[i] channels:    %d\n",      original->nChannels );
        printf( "[i] pixel depth: %d bits\n",   original->depth );
        printf( "[i] width:       %d pixels\n", original->width );
        printf( "[i] height:      %d pixels\n", original->height );
        printf( "[i] image size:  %d bytes\n",  original->imageSize );
        printf( "[i] width step:  %d bytes\n",  original->widthStep );

      // создаем первое окно для отображения камеры
        cvNamedWindow("Original",CV_WINDOW_AUTOSIZE);

      // Цикл захвата изображения оригинала.
      flag = true;
      while(flag){
         original = cvQueryFrame (capture);
         cvShowImage("Original", original);
         c = cvWaitKey(33);
         if (c == 13)flag = false; //Для захвата нажать "ENTER"
      }

      // задаем область ROI по центру изображения original
      int width_ROI = 50, heigth_ROI = 50;
      int x_ROI = original->width / 2 - width_ROI / 2, y_ROI = original->height / 2 - heigth_ROI / 2;
      int add = 200;

      // устанавливаем ROI
      cvSetImageROI(original, cvRect(x_ROI, y_ROI, width_ROI, heigth_ROI));
      
      // создаем 8-ми битную 3-канальную картинку-прицел sight
      sight = cvCreateImage(cvSize(width_ROI, heigth_ROI), 8, 3);
      // выводим в консоль информацию о "прицельном" изображении
      printf( "\r\n[i] Sight\n");
      printf( "[i] channels:    %d\n",      sight->nChannels );
        printf( "[i] pixel depth: %d bits\n",   sight->depth );
        printf( "[i] width:       %d pixels\n", sight->width );
        printf( "[i] height:      %d pixels\n", sight->height );
        printf( "[i] image size:  %d bytes\n",  sight->imageSize );
        printf( "[i] width step:  %d bytes\n",  sight->widthStep );

      // копируем изображение из области ROI с оригинала
      cvCopyImage(original, sight);
      assert( sight != 0 );

      // добавляем величину add оригинал для визуализации области ROI
      cvAddS(original, cvScalar(add), original);

      // сбрасываем ROI
      cvResetImageROI(original);
       
      // показываем изображение original с "прицелом"
        cvShowImage("Original",original);      

      // создаем второе окно для отображения с камеры
      cvNamedWindow("Capture", CV_WINDOW_AUTOSIZE);
      // создаем третье окно для отображения результата
        cvNamedWindow("Result",CV_WINDOW_AUTOSIZE);

      // создаем картинку result
      result = cvCreateImage(cvSize(original->width - sight->width + 1, original->height - sight->height + 1), 32, 1);
      double min, max;
      CvPoint minpos, maxpos;

      flag = true;
      while(flag){
         // получаем кадр
         frame = cvQueryFrame (capture);
         // обнулим resultat
         cvZero(result);

         // используем функцию сравнения регионов изображения
         cvMatchTemplate(frame, sight, result, CV_TM_CCOEFF_NORMED);
         cvNormalize(result, result, 1, 0, CV_MINMAX);
         cvMinMaxLoc(result, &min, &max, &minpos, &maxpos);
         cvCircle(frame, cvPoint(maxpos.x + sight->width / 2, maxpos.y + sight->height / 2), sight->height/2, cvScalar(0, 0, 255));
         //printf("\r\n%5.3f; x = %d; y = %d", max, maxpos.x, maxpos.y);
         
         cvShowImage("Capture", frame);
         cvShowImage("Result", result);

         c = cvWaitKey(33);
         if (c == 27) flag = false; // "Esc" для выхода
      }

        // освобождаем память, выделенную под изображения*/
        cvReleaseImage(&original);
      cvReleaseImage(&sight);
      cvReleaseImage(&frame);
      cvReleaseImage(&result);
      cvReleaseCapture(&capture);
        // закрываем окна и освобождаем выделенную память
      cvDestroyAllWindows();
        return 0;
}


Добавлено спустя 1 час 22 минуты:
Если кто-то хочет попробовать как оно работает (exe) :
Проект-1.rar
(1.02 МиБ) Скачиваний: 0

Камера должна быть воткнута в USB. "Enter" - захват картинки, "Esc" - выход.

Re: Нахождение части изображения на другом изображении

Zeus » 22 авг 2012, 17:04

Вчера немного изменил алгоритм с функцией cvMatchTemplate примерно так как предложил Romikgy.
Выкладывать код нет смысла, опишу примерно алгоритм.

С середины "оригинала" берется два изображения для будущего сравнения 50х50 и 100х100.
Соответственно два раза коррелируется кадр с камеры.
Получаем два максимума корреляции: maxpos1 и maxpos2.
Сравниваем их координаты X (maxpos1.x и maxpos2.x) и Y(maxpos1.y и maxpos2.y) на совпадение друг с другом с небольшим допуском, например <= 20 точек.

Если честно результат порадовал. Работает очень стабильно. Находит только "оригинал" причем там где он действительно есть, конечно если шибко камеру не вертеть на 360 градусов.

Среди минусов - низкая скорость работы.

Естественно столкнулся с проблемами (куда без них), например, если за оригинал взять и снять компьютерную клавиатуру с центром кадра 100х100 на кнопке "S-D-F", то при движении камеры вдоль клавиатуры, постоянно происходит определение соответствия и на других клавишах, так как они очень похожи.

Re: Нахождение части изображения на другом изображении

Angel71 » 22 авг 2012, 21:16

:) смотрят камеры на выключеный моник, по среди картинки всё чёрное, а вот ближе к краям вся полезная инфа. как поведёт себя алгоритм? второй момент - одно дело кнопки, где надписи видно и совсем другое одинаковые повторяющиеся объекты.

Re: Нахождение части изображения на другом изображении

Zeus » 23 авг 2012, 13:51

Это понятно, что на данном этапе такой алгоритм ничего в таком случае не найдет.
Но целью является поворот правой камеры стереозрения в ту точку куда смотрит левая.
Естественно, что если смотреть в "пустоту", то толку не будет, да и не надо так как объектов нет.

Естественно что человек видит все и сразу и хочет того же получить от машины...
Тут важно принять допуски на результат, что естественно ничего похожего на человеческое зрение мы не получим. И я больше чем уверен, что если, например алгоритм AVM EDV обучать на одинаковые повторяющиеся объекты или однотонные картинки, то толку будет мало.

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

Есть вроде еще гистограммы яркости? На вскиду какие функции в опенЦВ за это отвечают?

Re: Нахождение части изображения на другом изображении

Alex080969 » 23 авг 2012, 14:11

Сразу оговорюсь - в техническом зрении не мастак (всё времени не хватает).
Теперь по теме.
По исходным данным получается что мы поворачиваем камеру на неуий угол, берём с неё картинку, анализируем и вторая камера поворачивается.
Но может встоит ввести ограничение на скорость поворота первой камеры. Тогда при начале движения просчитывать кореляцию квадрата 50*50 не по всему кадру, а только по квадрату например 100*100, определяем в какую сторону происходит движение камеры, зная время обработки можно вычислить и скорость движения.

Re: Нахождение части изображения на другом изображении

Zeus » 23 авг 2012, 15:58

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

Re: Нахождение части изображения на другом изображении

EDV » 23 авг 2012, 19:32

Zeus писал(а):И я больше чем уверен, что если, например алгоритм AVM EDV обучать на одинаковые повторяющиеся объекты или однотонные картинки, то толку будет мало.

Не факт, так как у алгоритма AVM очень низкий процент ложных распознаваний: False Acceptance Rate (about 0.01 %). Так что если ваши «повторяющиеся» изображения всё же имеют некоторые отличия, то AVM может в этом случае отработать правильно.

Если есть желание, то я могу подготовить версию AVM v0.6 SDK и вы тогда сможете всё сами проверить в ваших экспериментах :wink:

Re: Нахождение части изображения на другом изображении

Zeus » 24 авг 2012, 16:12

EDV, честно слово не хотел никого обидеть.
За предложение SDK спасибо, но пока мне не нужно.
Я хочу прежде для себя разобраться.

Эксперименты конечно будут.
Вот только думаю, надо более менее повторяемый корректный стенд придумать и сделать.
Наверное угловые шкалы на основание приделать. Вот тогда будет эксперимент.

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


Rambler\'s Top100 Mail.ru counter