Перейти к содержимому
Compvision.ru
Виталий

Слежение за зрачком через вебкамеру

Recommended Posts

Задача: по изображению с камеры определить направление смотрения.

снимок получается с вебкамеры, лицо подсвечивается одним мощным светодиодом. пример в прикрепленном файле.

По снимку нужно определить относительное смещение зрачка и отражения( в координатах рисунка).

1) Определение отражения.

Использованные свойства: отражение наиболее яркое, круглое и находится на темном фоне.

после вычитания фона легко находиттся. Средняя ошибка около одного пиксела (при разрешении 640*480)

2) Определение координат зрачка

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

Помехи: отражение светодиода(решается закрашиванием), ресницы.

Придумал несколько способов как это сделать:

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

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

-детектор канни при некоторых параметрах размытия и значений порогов выдает приемлемые границы зрачка. Как лучше отфильтровать нужную границу и получить из нее примерный центр зрачка?

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

Интересует Ваше мнение как можно более точно и устойчиво к помехам определить координаты центра зрачка?

post-2009-0-43942400-1297293413_thumb.pn

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Окружности можно находить по-разному. Например, так:

int main()

{

	IplImage *img = cvLoadImage("d:\\eye.PNG");


	IplImage *bin_img = cvCreateImage(cvGetSize(img), 8, 1);

	cvCvtColor(img, bin_img, CV_RGB2GRAY);


	cvEqualizeHist(bin_img, bin_img);

	cvCanny(bin_img, bin_img, 50, 150);


	CvMemStorage *storage = cvCreateMemStorage(0);

	CvContourScanner traverse = cvStartFindContours(bin_img, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);


	for (CvSeq *contour = cvFindNextContour(traverse); contour; contour = cvFindNextContour(traverse))

	{

		if (contour->total > 6)

		{

			CvBox2D box = cvFitEllipse2(contour);

			CvPoint center = cvPointFrom32f(box.center);

			CvSize size = cvSize(cvRound(box.size.width * 0.5), cvRound(box.size.height * 0.5));


			// Проверка на окружность

			if ((double)box.size.width / (double)box.size.height > 0.9)

				cvEllipse(img, center, size, -box.angle, 0, 360, CV_RGB(0, 0, 255), 1, CV_AA, 0);

		}

	}


	cvEndFindContours(&traverse);

	cvReleaseMemStorage(&storage);


	cvShowImage("1", img);

	cvShowImage("2", bin_img);


	for (;

	{

		if (cvWaitKey(10) > 0)

			break;

	}


	cvReleaseImage(&bin_img);

	cvReleaseImage(&img);


	return 0;

}[/code]

В результате есть и ложные сработки, но их можно отфильтровать по "вторичным половым признакам":

post-391-0-63484400-1297367781_thumb.png

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Сейчас попробую перейти от детектора канни к адаптивному порогу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Для лучшего выделения контуров ещё можно усилить контрастность в определённом диапазоне яркостей. Не знаю на счёт OpenCV (есть в Фотошопе), но и самому реализовать довольно просто:

1. если яркость пикселя I[x, y] ниже некоторого нижнего порога t, то I[x, y] = k * I[x, y], где 0 > k < 1;

2. если яркость пикселя I[x, y] выше некоторого верхнего порога T, то I[x, y] = min(255, K * I[x, y]), где 1 > k < 2;

3. 0 < t < T < 255.

Подбирая нижний и верхний пороги, а также коэффициенты усиления и ослабления можно добиться неплохого выделения исходного объекта, если тот находится на фоне с другой яркостью.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Написал и самому стало интересно - будет ли оно работать. Набросал кусочек, попробуй вставить его вместо cvEqualizeHist:

unsigned char t = 10;

unsigned char T = 20;

double k = 0.2;

double K = 1.5;


for (unsigned char *pbuf = (unsigned char *)bin_img->imageData, *stop = (unsigned char *)(bin_img->imageData + bin_img->imageSize); pbuf < stop; ++pbuf)

{

	if (pbuf[0] < t)

	{

		pbuf[0] = (unsigned char)(k * (double)pbuf[0]);

	}

	else if (pbuf[0] > T)

	{

		pbuf[0] = (unsigned char)std::min(255., K * (double)pbuf[0]);

	}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я понял,что ты имел ввиду, Nuzhny. Такое преобразование должно быть непрерывным. В твоем случае получится разрыв с уровнем по яркости t и T, поэтому появится лишняя граница по этому уровню

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

эксперименты с алгоритмами к более лучшему результату не превели.

Теперь есть другая задача: имеется некоторое отображение точек из одной плоскости в другую. мы знаем координаты образа и прообраза нескольких точек. Как по этим данным найти наиболее точное отображение? Наверняка есть некоторые функции opencv, но какие?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

cvFindHomography

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Случайно наткнулся на достаточно новую статью по теме: "REAL-TIME CALIBRATION-FREE AUTONOMOUS EYE TRACKER" Klefenz, Husar, Krenzer, Hess

Там подход посложнее рассматривается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Там используется пороговое преобразование зрачка. у меня данный метод не прокатил - самые яркие пиксели зрачка ярче темных пикселей роговицы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здраствуйте. Интересует следующий вопрос.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Реально. Но необходимо хорошее освещение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Уже хорошо. А какие API функции opncv вы порекомендовали бы использовать для реализации данной задачи?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Сначала должен быть алгоритм, хотя бы в общих чертах, а функции это дело третье.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вот вкратце, что я хотел бы видеть и как я это себе представляю.

В этой сфере я новичок, поэтому прошу сильно не пинать.

Что я хочу получить в итоге:

При повороте головы (в конечном варианте - зрачка), моя программа должна выполнять некие действия.

Возможные положения (влево, вправо, вверх, вниз). Главное условия, чтобы программа четко детектировала

данные положения головы (зрачка), без ошибок, ну или с в большей степенью вероятности (не меньше 80%)

Как я себе это представляю. Примерный алгоритм.

1) Получаю снимок с камеры, выделяю лицо каскадами хаара. Кстати есть более надежные методы?

2) Выделенный паттерн лица, распознать методами (EigenFace, Hide-Mark-Model).

К примеру имеется в базе имеется 4 паттерна (т.е. для различных положений головы).

В базе есть сл. паттерны.

а) Фронтальный вид лица.

б) Где лицо чуть повернуто влево (не в профиль)

в) Где лицо чуть повернуто вправо (не в профиль)

г) Лицо повернуто вверх

д) Лицо повернуто вниз

Распознать и выделить паттерн, который наиболее совпадает.

Тем самым в дальнейшем интерпретировать картинки -> в действия.

Вот как я себе это представляю. А теперь вопросы.

Насколько это будет надежно? Есть более продвинутые методы? (слышал о технологии трехмерной модели головы).

Какие функции opencv можно было бы использовать для настройки резкости изображения, удаления шумов, и т.п.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×