Распознавание образов для программистов

ВНИМАНИЕ! БЛОГ ПЕРЕЕХАЛ ПО АДРЕСУ
RECOG.RU

14 Май 2011

Определение положения второй камеры с помощью баскетбольного мяча

написано в рубрике: Стереозрение — Кручинин Александр @ 8:04 ПП

Пусть есть две камеры, оси которых параллельны друг другу. Необходимо, зная положение в пространстве одной камеры, определить положение второй (Рис.1). Данную задачу можно решить с помощью обычного баскетбольного мяча.

Читать дальше )

18 Февраль 2011

Особенности и стереозрение

написано в рубрике: Стереозрение — Кручинин Александр @ 2:26 ПП

Статья про применение особенностей в стереозрении:

http://www.isr.uc.pt/~urbano/WorkIROS09/images/PDF/WorkIROS09-RobustFeature.pdf

Annalisa Milella, Bruno Nardelli, Donato Di Paola, and Grazia Cicirelli

Robust Feature Detection and Matching for Vehicle Localization in Uncharted Environments

Вообщем то, что делал я (чуть позже, не зная этой работы) на модели

http://blog.vidikon.com/?p=267

Они опробывали на роботе

stereo_1

31 Август 2010

Тестирование стереозрения на 3D модели 2

написано в рубрике: Стереозрение — Кручинин Александр @ 2:31 ПП

Данный ролик показывает пример работы алгоритмов стереозрения на 3D модели. Осуществляется слежение за шаром.

Большое окно – сцена:

Левая и правая камеры – могут находится как на шаре, так и фиксировано на одной из стен.

Снизу окошко “Out” показывает место где определяется местоположение шара при помощи стереозрения на сцене.

По-сравнению с версией http://blog.vidikon.com/?p=342 изменени положение камер для покрытия почти всей сцены, добавлены области видимости камер и увеличено результирующее окно “Out”.

Если вам не нравится качество youtube, то можете скачать ролик отсюда:

http://vidikon.com/download/modelstereovison.avi

Дальнейшими тестами должно стать изменение направлений камер на разные углы

18 Август 2010

Тестирование стереозрения на 3D модели

написано в рубрике: Стереозрение — Кручинин Александр @ 8:38 ПП

Данный ролик показывает пример работы алгоритмов стереозрения на 3D модели. Осуществляется слежение за шаром.

Большое окно – сцена:

Левая и правая камеры – могут находится как на шаре, так и фиксировано на одной из стен.

Снизу окошко “Out”  показывает место где определяется местоположение шара при помощи стереозрения на сцене.

Работают одновременно 3 программы.

Если вам не нравится качество youtube, то можете скачать ролик отсюда:

http://vidikon.com/download/capture-1.avi

1 Июль 2010

31. Калибровка камер с использованием «креста»

написано в рубрике: ImagePak, OpenCV, Стереозрение — Кручинин Александр @ 5:37 ПП

В OpenCV есть процедура калибровки камер на основе шахматной доски, но калибровать камеры (в нашем понимании это будет определение углов обзора и расстояний между камерами) можно с использованием «креста». Пусть есть 2 камеры (Рис. 31.1).

Рис. 31.1. 2 камеры

Рис. 31.1. 2 камеры

С помощью фломастера или маркера рисуем на чистом листке (желательно плотном) крест (Рис. 31.2).

Рис. 31.2. Крест можно нарисовать и пожирнее

Рис. 31.2. Крест можно нарисовать и пожирнее

Далее пишем простейшую программу получения двух изображений с двух камер (Листинг 31.1).

Листинг 31.1

// cal.cpp : Defines the entry point for the console application.

//

#include “stdafx.h”

#include “cv.h”

#include “highgui.h”

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <math.h>

#include <float.h>

#include <limits.h>

#include <time.h>

#include <ctype.h>

DWORD WINAPI Func(LPVOID);

int _tmain(int argc, _TCHAR* argv[])

{

CvCapture* capture = 0;

capture = cvCaptureFromCAM(0 );

cvNamedWindow( “Motion”, 1 );

DWORD lpT;

HANDLE h=CreateThread(NULL,0,Func,NULL,0,&lpT);

CloseHandle(h);

for(;;)

{

IplImage* image1;

if( !cvGrabFrame( capture ))

break;

image1 = cvRetrieveFrame( capture );

cvShowImage( “Motion”, image1);

if( cvWaitKey(10) >= 0 ) break;

}

cvReleaseCapture( &capture );

cvDestroyWindow( “Motion” );

return 0;

}

DWORD WINAPI Func(LPVOID)

{

CvCapture* capture = 0;

capture = cvCaptureFromCAM(1 );

cvNamedWindow( “Motion1″, 1 );

for(;;)

{

IplImage* image1;

if( !cvGrabFrame( capture ))

break;

image1 = cvRetrieveFrame( capture );

cvShowImage( “Motion1″, image1);

if( cvWaitKey(10) >= 0 ) break;

}

cvReleaseCapture( &capture );

cvDestroyWindow( “Motion1″ );

return 0;

}

Как вы заметили, используются два отдельных потока. Затем на каждом видео потоке необходимо искать местонахождение креста. Я это сделал так, как показано в листинге 31.2.

Листинг 31.2

// cal.cpp : Defines the entry point for the console application.

//

#include “stdafx.h”

#include “cv.h”

#include “highgui.h”

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <math.h>

#include <float.h>

#include <limits.h>

#include <time.h>

#include <ctype.h>

#include “imagepak.h”

DWORD WINAPI Func(LPVOID);

int porog=150;

int test=0;

//крест в ширину мм

double lkrest=0.106;

double x1,x2;

C_POINTd p1,p2;

IMG Img9OpenCVtoImagePak(IplImage*);

int _tmain(int argc, _TCHAR* argv[])

{

CvCapture* capture = 0;

capture = cvCaptureFromCAM(0 );

cvNamedWindow( “Motion”, 1 );

cvNamedWindow( “Motion_1″, 1 );

DWORD lpT;

HANDLE h=CreateThread(NULL,0,Func,NULL,0,&lpT);

CloseHandle(h);

IplImage* object=0;

IMG img8;

RECT rect;

for(;;)

{

IplImage* image1;

if( !cvGrabFrame( capture ))

break;

image1 = cvRetrieveFrame( capture );

if (!object)

{

object = cvCreateImage(cvGetSize(image1), 8, 1);

cvZero( object );

object->origin = image1->origin;

rect.left=0;rect.top=0;

rect.right=image1->width-1;

rect.bottom=image1->height;

//Здесь необходимо вызвать функцию перевода изображений

}

cvCvtColor( image1, object, CV_BGR2GRAY );

cvThreshold( object, object, porog, 255, CV_THRESH_BINARY );

int i,j,k,all;

C_POINT c_p[4];

C_POINT center;

try{

img8=Img9OpenCVtoImagePak(object);

AllocationBordersRect(img8,rect,ALLOCATE_WHITE);

CONTOUR Contour;

Contour.Find(img8,rect,128,CONTOUR_AUTO_INOUT);

all=Contour.ReturnAllContours();

if (all>0)

{

Contour.ReturnMaxLevel(i,j,k);

i=Contour.Return4DistantPoints(c_p[0],j);

}else i=-1;

}

catch (…)

{

i=-1;

}

//k=Contour.ReturnAllContours;

if (i!=0) ;

else

{

//нашли четыре точки

int xmin,xmax,ymin,ymax;

xmin=c_p[0].x;

xmax=c_p[0].x;

ymin=c_p[0].y;

ymax=c_p[0].y;

for(i=1;i<4;i++)

{

if (c_p[i].x<xmin) xmin=c_p[i].x;

if (c_p[i].x>xmax) xmax=c_p[i].x;

if (c_p[i].y<ymin) ymin=c_p[i].y;

if (c_p[i].y>ymax) ymax=c_p[i].y;

}

if (xmin>100 && xmax<540 && ymin>80 && ymax<400)

{

CvPoint center;

CvScalar color;

color = CV_RGB(255,0,0);

for(i=0;i<4;i++)

{

center = cvPoint(c_p[i].x,

c_p[i].y);

cvCircle( image1, center, 10, color, 3, CV_AA, 0 );

}

if (test==2)

{

//ищем линии и пересечения

F_LINE liness[2];

liness[0]=MakeLine(c_p[0],c_p[1]);

liness[1]=MakeLine(c_p[2],c_p[3]);

//Какие у нас левые точки а какие правые

int ll,rr;

ll=0;rr=0;

for(i=1;i<4;i++)

{

if (c_p[i].x<c_p[ll].x) ll=i;

if (c_p[i].x>c_p[rr].x) rr=i;

}

x1=320*lkrest/sqrt((double)pow((double)c_p[rr].x-c_p[ll].x,2)+(double)pow((double)c_p[rr].y-c_p[ll].y,2));

Intersection(liness[0],liness[1],p1.x,p1.y);

test=1;

}

}

}

delete img8.bytes;

cvShowImage( “Motion”, image1);

cvShowImage( “Motion_1″, object);

if( cvWaitKey(10) >= 0 ) break;

}

cvReleaseCapture( &capture );

cvDestroyWindow( “Motion” );

return 0;

}

DWORD WINAPI Func(LPVOID)

{

CvCapture* capture = 0;

capture = cvCaptureFromCAM(1 );

cvNamedWindow( “Motion1″, 1 );

cvNamedWindow( “Motion1_1″, 1 );

IplImage* object=0;

IMG img8;

RECT rect;

for(;;)

{

IplImage* image1;

if( !cvGrabFrame( capture ))

break;

image1 = cvRetrieveFrame( capture );

if (!object)

{

object = cvCreateImage(cvGetSize(image1), 8, 1);

cvZero( object );

object->origin = image1->origin;

rect.left=0;rect.top=0;

rect.right=image1->width-1;

rect.bottom=image1->height;

}

cvCvtColor( image1, object, CV_BGR2GRAY );

cvThreshold( object, object, porog, 255, CV_THRESH_BINARY );

int i,j,k,all;

C_POINT c_p[4];

C_POINT center;

try{

img8=Img9OpenCVtoImagePak(object);

AllocationBordersRect(img8,rect,ALLOCATE_WHITE);

CONTOUR Contour;

Contour.Find(img8,rect,128,CONTOUR_AUTO_INOUT);

all=Contour.ReturnAllContours();

if (all>0)

{

Contour.ReturnMaxLevel(i,j,k);

i=Contour.Return4DistantPoints(c_p[0],j);

}else i=-1;

}

catch(…)

{

i=-1;

}

if (i!=0 ) ;

else

{

//нашли четыре точки

int xmin,xmax,ymin,ymax;

xmin=c_p[0].x;

xmax=c_p[0].x;

ymin=c_p[0].y;

ymax=c_p[0].y;

for(i=1;i<4;i++)

{

if (c_p[i].x<xmin) xmin=c_p[i].x;

if (c_p[i].x>xmax) xmax=c_p[i].x;

if (c_p[i].y<ymin) ymin=c_p[i].y;

if (c_p[i].y>ymax) ymax=c_p[i].y;

}

if (xmin>100 && xmax<540 && ymin>80 && ymax<400)

{

CvPoint center;

CvScalar color;

color = CV_RGB(255,0,0);

for(i=0;i<4;i++)

{

center = cvPoint(c_p[i].x,

c_p[i].y);

cvCircle( image1, center, 10, color, 3, CV_AA, 0 );

}

if (test==1)

{

//ищем линии и пересечения

F_LINE liness[2];

liness[0]=MakeLine(c_p[0],c_p[1]);

liness[1]=MakeLine(c_p[2],c_p[3]);

//Какие у нас левые точки а какие правые

int ll,rr;

ll=0;rr=0;

for(i=1;i<4;i++)

{

if (c_p[i].x<c_p[ll].x) ll=i;

if (c_p[i].x>c_p[rr].x) rr=i;

}

x2=320*lkrest/sqrt((double)pow((double)c_p[rr].x-c_p[ll].x,2)+(double)pow((double)c_p[rr].y-c_p[ll].y,2));

Intersection(liness[0],liness[1],p2.x,p2.y);

test=0;

FILE *f;

…//Считаем что надо

fclose(f);

}

}

}

delete img8.bytes;

cvShowImage( “Motion1″, image1);

cvShowImage( “Motion1_1″, object);

k=cvWaitKey(10);

if( k >= 0 ) {

if (k==32) test=2;

else break;

}

}

cvReleaseCapture( &capture );

cvDestroyWindow( “Motion1″ );

return 0;

}

//Только для 8-битных серых – не учитывает переворот

IMG Img9OpenCVtoImagePak(IplImage* im)

{

IMG img;

img.format=1;

img.on=1;

img.Width=im->width;

img.Height=im->height;

if (img.Width%4==0) img.Width_1=img.Width;

else img.Width_1=img.Width+4-img.Width%4;

img.bytes=new byte[img.Width_1*img.Height];

uchar* ptr;

ptr = (uchar*) (im->imageData);

for(int i=0;i<img.Height;i++)

for(int j=0;j<img.Width;j++)

img.bytes[j+i*img.Width_1]=ptr[j+i*im->widthStep];

return img;

}

В некоторых местах я просто копировал код, не применяя отдельных функций, дабы быстрее написать. В программе используются функции из библиотеки ImagePak, которую я в скором времени выложу в свободный доступ. В частности функция Img9OpenCVtoImagePak, привёдённая здесь конвертирует изображение из формата OpenCV в формат ImagePak.

Суть нахождения креста в следующем:

  1. AllocationBordersRect – находятся граничные точки.
  2. Contour.Find – ищутся все контура на изображении.
  3. Если контуров больше 0, то вызывается Contour.ReturnMaxLevel для определения контура наибольшей вложенности (это не совсем правильно, но работает).
  4. Contour.Return4DistantPoints – находятся 4 наиболее удалённые точки на контуре, которые являются четырьмя концами «креста»

Результат смотрите на рисунке 31.3.

Рис.31.3. Выделение креста

Рис.31.3. Выделение креста

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

Старые записи »

Работает на WordPress