Технический форум по робототехнике.
Zeus » 15 авг 2012, 14:38
Имеем две камеры. Первая камера наводится вручную, Вторая сервоприводами вверх-вниз, влево-вправо.
Камеры стоят на одной оси - типа стереозрение.
Первую камеру выставляем вручную.
Вторая камера должна повернуться туда-же куда смотрит первая, естественно с определенной долей погрешности.
В общем я так себе это представляю:
На изображении полученном с Первой камеры - выделяется участок вокруг центра изображения, например 100х100 точек. С ним делаются какие-нить преобразования...
Потом этот участок ищется на изображении со второй камеры и с помощью сервоприводов камера поворачивается так что данный участок оказывается тоже в центре изображения, естественно с определенной долей вероятности, так как угол под которым видит камера уже другой.
Определение и выделение объектов на изображении не интересует.
Как это сделать? Какие методы использовать?
Имеется ввиду использование OpenCV
Romikgy » 15 авг 2012, 15:12
не в курсе как в OpenCV , а вообще корреляцией ... сорри если не в тему...
Zeus » 15 авг 2012, 15:47
Почему не в тему?! как раз в тему.
Только на сколько я понимаю корреляция всего изображения будет перебором делаться под размер образца образец, а это наверное будет долго.
Может сперва по цветам искать, а потом корреляцию?
или есть что пошустрее?
Romikgy » 15 авг 2012, 16:20
тогда могу предложить поиск в 2 этапа :
1. берем малый квадрат инфы , допустим 16х16 с верхнего левого угла , и исчим корреляцию по всей картинке , при совпадении более 50-90 % второй шаг
2. корреляция всего участка 100х100 от последней координаты совпадения...
Madf » 15 авг 2012, 16:48
не забываем, что изображение с 1 камеры будет одно, а с 2 - другое, ибо стоять будет под другим углом (или этим можно пренебречь, если расстояние до снимаемого объекта далеко)
Romikgy » 15 авг 2012, 16:57
имхо задача и есть в том , что бы направить 2 камеру туда же , куда смотрит первая.....
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
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) :
Камера должна быть воткнута в USB. "Enter" - захват картинки, "Esc" - выход.
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", то при движении камеры вдоль клавиатуры, постоянно происходит определение соответствия и на других клавишах, так как они очень похожи.
Angel71 » 22 авг 2012, 21:16
смотрят камеры на выключеный моник, по среди картинки всё чёрное, а вот ближе к краям вся полезная инфа. как поведёт себя алгоритм? второй момент - одно дело кнопки, где надписи видно и совсем другое одинаковые повторяющиеся объекты.
Zeus » 23 авг 2012, 13:51
Это понятно, что на данном этапе такой алгоритм ничего в таком случае не найдет.
Но целью является поворот правой камеры стереозрения в ту точку куда смотрит левая.
Естественно, что если смотреть в "пустоту", то толку не будет, да и не надо так как объектов нет.
Естественно что человек видит все и сразу и хочет того же получить от машины...
Тут важно принять допуски на результат, что естественно ничего похожего на человеческое зрение мы не получим. И я больше чем уверен, что если, например алгоритм AVM EDV обучать на одинаковые повторяющиеся объекты или однотонные картинки, то толку будет мало.
Вопрос в другом: как можно улучшить распознавание центра картинки, чтобы быстрее работало, потому как корреляция происходит очень медленно.
Есть вроде еще гистограммы яркости? На вскиду какие функции в опенЦВ за это отвечают?
Alex080969 » 23 авг 2012, 14:11
Сразу оговорюсь - в техническом зрении не мастак (всё времени не хватает).
Теперь по теме.
По исходным данным получается что мы поворачиваем камеру на неуий угол, берём с неё картинку, анализируем и вторая камера поворачивается.
Но может встоит ввести ограничение на скорость поворота первой камеры. Тогда при начале движения просчитывать кореляцию квадрата 50*50 не по всему кадру, а только по квадрату например 100*100, определяем в какую сторону происходит движение камеры, зная время обработки можно вычислить и скорость движения.
Zeus » 23 авг 2012, 15:58
Скорее всего искать не по всему изображению, а по 100х100 плюс поворот непонятно в какую сторону - будет еще медленней, чем сразу по всему кадру.
EDV » 23 авг 2012, 19:32
Zeus писал(а):И я больше чем уверен, что если, например алгоритм AVM EDV обучать на одинаковые повторяющиеся объекты или однотонные картинки, то толку будет мало.
Не факт, так как у алгоритма AVM очень низкий процент ложных распознаваний:
False Acceptance Rate (about 0.01 %). Так что если ваши «повторяющиеся» изображения всё же имеют некоторые отличия, то AVM может в этом случае отработать правильно.
Если есть желание, то я могу подготовить версию
AVM v0.6 SDK и вы тогда сможете всё сами проверить в ваших экспериментах
Zeus » 24 авг 2012, 16:12
EDV, честно слово не хотел никого обидеть.
За предложение SDK спасибо, но пока мне не нужно.
Я хочу прежде для себя разобраться.
Эксперименты конечно будут.
Вот только думаю, надо более менее повторяемый корректный стенд придумать и сделать.
Наверное угловые шкалы на основание приделать. Вот тогда будет эксперимент.
Я все-таки склоняюсь к тому? что изображение-шаблон надо разбивать на более мелкие, например на 4 (пополам по горизонтали и по вертикали).
Соответственно для каждой части и его целого находить его собственные и индивидуальные параметры. И поиск делать сперва по-маленьким частям, а когда он будут находится, то расширять поиск вокруг найденной области до всего размера изображения-шаблона.
И поиск сперва наверное делать по цветности, а не по яркости. Смысл искать по яркости, если шаблон зеленый а в кадре вообще зеленого ничего нет.