open frameworks и opencv

43
Разработка интерактивных систем на OpenFrameworks 5. OpenFrameworks и OpenCV УрГУ / ИММ весна 2011 лекции и объявления: www.uralvision.blogspot.com вопросы по проектам и программированию: [email protected]

Upload: denis-perevalov

Post on 14-Oct-2014

2.547 views

Category:

Documents


6 download

DESCRIPTION

Лекция про совместное использование OpenFrameworks и OpenCV, с введением в OpenCV.

TRANSCRIPT

Page 1: Open Frameworks и OpenCV

Разработка интерактивных систем на OpenFrameworks

5. OpenFrameworks

и OpenCV

УрГУ / ИММ весна 2011

лекции и объявления: www.uralvision.blogspot.com

вопросы по проектам и программированию: [email protected]

Page 2: Open Frameworks и OpenCV

Анализ и изменение изображенийВ openFrameworks для изменения изображений ofImage используется такая схема:

1. Получить байты изображения unsigned char* data = image.getPixels(); int w = image.width; int h = image.height;//Данные не копируются, и удалять не надо!!

2. Обработатьпостроить новое изображение data1unsigned char* data1 = new unsigned char *[w * h * 3];....заполняем data1, используя data

3. Вставить байты в изображениеimage.setFromPixels( data1, w, h, OF_IMAGE_COLOR );

//OF_IMAGE_COLOR - 3-байтный цвет.//OF_IMAGE_GRAYSCALE - 1-байтный серый.//OF_IMAGE_COLOR_ALPHA - 4-байтные, цвет + прозрачность.

Page 3: Open Frameworks и OpenCV

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

В openFrameworks есть аддон - ofxOpenCv.

На сегодняшний день (апрель 2011) он работает с OpenCV 1.x. Эта версия OpenCV неудобна тем, что имеет лишь C-интерфейс.

Поэтому мы изучим более удобный OpenCV 2.x и будем его использовать, без аддона ofxOpenCv.

Page 4: Open Frameworks и OpenCV

OpenFrameworks и OpenCVВ OpenCV изображения задаются классом Mat.

Как конвертировать ofImage в Mat и обратно, на примере 3-канальных изображений:

Из openFrameworks в OpenCV

ofImage image; //-пусть оно есть, 3-канальное...Mat imageCV( cv::Size( image.width, image.height ), CV_8UC3, image.getPixels() );

Из OpenCV в openFrameworks

Mat imageCV; //-путь оно есть, 3-канальное...image.setFromPixels( (unsigned char*)IplImage(imageCV).imageData, imageCV.size().width, imageCV.size().height, OF_IMAGE_COLOR );

Page 5: Open Frameworks и OpenCV

Знакомство с OpenCV

- Что такое OpenCV- Первый проект на OpenCV- Класс Mat- Функции обработки изображений

Page 6: Open Frameworks и OpenCV

Что такое OpenCV

"Open Computer Vision Library" Открытая библиотека с набором функций для обработки, анализа и распознавания изображений, C/C++.

Page 7: Open Frameworks и OpenCV

Что такое OpenCV

2000 - первая альфа-версия, поддержка Intel, C-интерфейс

2006 - версия 1.0

2008 - поддержка Willow Garage (лаб. робототехники)

2009 - версия 2.0, классы С++

2010 - версия 2.2, реализована работа с GPU

Page 8: Open Frameworks и OpenCV

Первый проект на OpenCV 1. Создание проектаПредполагаем, что Microsoft Visual C++ 2008 Express Edition и OpenCV 2.1 уже установлены.

1. Запускаем VS2008

2. Создаем консольный проектFile - New - Project - Win32 Console Application, в Name ввести Project1, нажать ОК.

3. Настраиваем путиAlt+F7 - откроется окно свойств проектаConfiguration Properties - C/C++ - General - Additional Include Directories,там ставим значение "C:\Program Files\OpenCV2.1\include\opencv";

Linker - General - Additional Library Directories, там ставим значениеC:\Program Files\OpenCV2.1\lib\

Linker - Input - Additional Dependencies - cv210.lib cvaux210.lib cxcore210.lib cxts210.lib highgui210.lib для Release,cv210d.lib cvaux210d.lib cxcore210d.lib cxts210.lib highgui210d.lib для Debug

Page 9: Open Frameworks и OpenCV

Первый проект на OpenCV 2. Считывание изображения и показ его на экране 1. Готовим входные данные:файл http://www.fitseniors.org/wp-content/uploads/2008/04/green_apple.jpgпишем в C:\green_apple.jpg 2. Пишем в Project1.cpp:#include "stdafx.h"#include "cv.h"#include "highgui.h" using namespace cv;

int main( int argc, const char** argv ){ Mat image = imread( "C:\\green_apple.jpg" ); //Загрузить изображение с диска imshow( "image", image ); //Показать изображение waitKey( 0 ); //Ждем нажатия клавиши return 0;} 3. Нажимаем F7 - компиляция, F5 - запуск. Программа покажет изображение в окне, и по нажатию любой клавиши завершит свою работу.

Page 10: Open Frameworks и OpenCV

Первый проект на OpenCV 3. Линейные операции над изображениями

Заменяем текст в main из предыдущего примера на:

int main( int argc, const char** argv ){ Mat image = imread( "C:\\green_apple.jpg" ); //image1 попиксельно равен 0.3*image Mat image1 = 0.3 * image; imshow( "image", image ); imshow( "image1", image1 ); waitKey( 0 ); return 0; }

Page 11: Open Frameworks и OpenCV

Первый проект на OpenCV 4. Работа с прямоугольными подобластями изображенияЗаменяем текст в main из предыдущего примера на:

int main( int argc, const char** argv ){ Mat image = imread( "C:\\green_apple.jpg" ); //Вырезание части картинки Rect rect = Rect(100, 100, 200, 200); //прямоугольник вырезания Mat image3; image( rect ).copyTo( image3 ); //копирование части image imshow( "image3", image3 );

//Изменение части картинки внутри самой картинки image( rect ) *= 2; imshow( "image changed", image );

waitKey( 0 ); return 0; }

Page 12: Open Frameworks и OpenCV

Класс Mat

Mat - основной класс для хранения изображений OpenCV.

Page 13: Open Frameworks и OpenCV

Изображение является матрицей пикселов.Каждый пиксел может хранить некоторые данные.Если пиксел хранит векторные данные, то размерность вектора называется числом каналов изображения.

1-канальные изображения - называют еще полутоновыми3-канальные изображения - обычно состоят из трех компонент (Red, Green, Blue).

Также, в OpenCV можно использовать 2- и 4-канальные изображения.

Класс MatОдно- и многоканальные изображения

Page 14: Open Frameworks и OpenCV

Класс MatСоздание изображений

1) Пустое изображение без определенного типа

Mat imageEmpty;

2) Изображение w x h пикселов, значения 0..255 (8U значит "unsigned 8 bit", C1 значит "один канал"):

int w=150; int h=100;Mat imageGray( cv::Size( w, h ), CV_8UC1 );

Page 15: Open Frameworks и OpenCV

3) 1-канальное со значениями с плавающей точкой (32F значит "float 32 bit"):

Mat imageFloat( cv::Size(w, h), CV_32FC1 );

4) 3-канальное изображения со значениями 0..255 в каждом канале:

Mat imageRGB( cv::Size(w, h), CV_8UC3 );

Класс MatСоздание изображений

Page 16: Open Frameworks и OpenCV

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

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

Image imageFloat;imageGray.convertTo( imageFloat, CV_32FC1, 1.0 / 255.0 ); - здесь OpenCV сам выделит память под imageFloat.Важно, что если изображение уже нужного размера, то никаких операций по выделению памяти не производится.

2. Операции присваивания осуществляются не копированием данных (как это делает std::vector), и не путем копирования указателей, а с использованием механизма счетчика ссылок.

Класс MatУправление памятью

Page 17: Open Frameworks и OpenCV

Механизм счетчика ссылок (в STL это shared_ptr, в Java он на всех указателях) работает так:{Mat A( cv::Size( 100, 100 ), CV_8UC1 ); //выделилась память под изображение, при этом запомнилось, //что эта память используется одним изображением.{Mat B = A;//Тут память под изображение не выделяется, а просто //данные в B указывают на ту же область в памяти. //Поэтому, если менять B, то изменится и A. //Счетчик ссылок изображения увеличился, стал равным 2.}//Тут B вышло из области видимости, счетчик ссылок уменьшился, //и стал равен 1.}//Тут A вышло из области видимости, счетчик ссылок стал равен 0,//и память, выделенная для него, автоматически очищается.

Класс MatУправление памятью

Page 18: Open Frameworks и OpenCV

Так как операция Mat B = A; не копирует изображение A в B, то для того, чтобы создать копию изображения для последующего независимого использования, нужно применять явные команды copyTo и clone:

image1.copyTo( image2 );image3 = image1.clone();

Класс MatУправление памятью

Page 19: Open Frameworks и OpenCV

Итог: 1) операция присваивания Mat B = A; работает очень быстро, и не осуществляет копирование данных, а настраивает специальным образом указатели на них. Это позволяет передавать Mat в функции прямо, без указателей и ссылок. При этом не возникнет нежелательного копирования Mat в стек (как это бы сталал std::vector).

Хотя, конечно, const Mat & будет передаваться все равно быстрее.

2) для копирования изображений нужно пользоваться явными командами copyTo и clone.

Класс MatУправление памятью

Page 20: Open Frameworks и OpenCV

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

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

Класс MatПопиксельный доступ к изображениям

Page 21: Open Frameworks и OpenCV

Один из способов доступа к пикселам для изображений, у которых известен тип - использование метода at. Для одноканального изображения 0...255 это делается так:

//Взятие значенияint value = imageGray.at<uchar>(y, x);

//Установка значенияimageGray.at<uchar>(y, x) = 100;

Обратите внимание, что x и y в вызове переставлены местами.

Класс MatПопиксельный доступ к изображениям

Page 22: Open Frameworks и OpenCV

ПримечаниеПри выводе на экране изображений с плавающей точкой средствами OpenCV надо иметь в виду, что они отображаются в предположении, что их значения лежат в [0,1]. Поэтому при конвертации 8-битных изображений в изображения с плавающей точкой нужно делать трансформацию — умножение на 1.0 / 255.0.

Для конвертации типов изображений разной битности (float и unsigned char) используется член класса convertTo. В нем второй параметр — тип получаемого изображения.

imageGray.convertTo( imageFloat, CV_32FC1, 1.0 / 255.0 );

Число каналов входа и выхода должно совпадать!

Класс MatКонвертация типов

Page 23: Open Frameworks и OpenCV

Для конвертации различных цветовых пространств используется функция cvtColor. При необходимости она способна менять число каналов.

Например, конвертация 3-канального RGB-изображения в полутоновое:

cvtColor( inputRGB, outputGray, CV_BGR2GRAY );

наоборот:cvtColor( inputGray, outputRGB, CV_GRAY2BGR );

Класс MatКонвертация типов

Page 24: Open Frameworks и OpenCV

Класс MatРазбиение на каналы

Функция split разбивает многоканальное изображение на каналы.Функция merge склеивает несколько одноканальных изображений в многоканальное.

void split ( const Mat& mtx, //исходное цветное изображение vector<Mat>& mv //результирующий набор 1-канальных //изображений )

void merge ( const vector<Mat>& mv, //исходный набор 1-канальных //изображений Mat& dst //результирующее цветное //изображение )

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

Page 25: Open Frameworks и OpenCV

Класс MatРазбиение на каналы

int main( int argc, const char** argv ){ Mat image = imread( "C:\\green_apple.jpg" ); //Разделение исходной картинки на три канала // - channels[0], channels[1], channels[2] vector<Mat> channels; split( image, channels ); //Показываем каналы в отдельных окнах //Обратите внимание, что красный канал - 2, а не 0. imshow( "Red", channels[2] ); imshow( "Green", channels[1] ); imshow( "Blue", channels[0] ); waitKey( 0 ); return 0; }

Page 26: Open Frameworks и OpenCV

Функции обработки изображенийСглаживание

Функция GaussianBlur осуществляет сглаживание изображение фильтром Гаусса.

Чаще всего сглаживание применяется для устранения мелкого шума на изображении, для последующего анализа изображения. Делается с помощью фильтра небольшого размера.

Исходное изображение Изображение, сглаженное окном 11 x 11

http://www.innocentenglish.com/funny-pics/best-pics/stairs-sidewalk-art.jpg

Page 27: Open Frameworks и OpenCV

Функции обработки изображенийПороговая обработка

Функция threshold осуществляет пороговую обработку изображения.

Чаще всего она применяются для выделения пикселов интересующих объектов на изображении.

http://www.svi.nl/wikiimg/SeedAndThreshold_02.png

Page 28: Open Frameworks и OpenCV

Функции обработки изображенийЗаливка областей

Функция floodFill осуществляет заливку области, начиная из некоторого пиксела (x, y), с заданными границами останова, используя 4- или 8- смежность пикселов.

Важно: она портит исходное изображение - так как заливает его.

Чаще всего она применяется для выделения областей, выделенных путем пороговой обработки, для последующего их анализа.

http://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Square_4_connectivity.svg/300px-Square_4_connectivity.svg.pnghttp://tunginobi.spheredev.org/images/flood_fill_ss_01.png

Page 29: Open Frameworks и OpenCV

Функции обработки изображенийВыделение контуров

Контур объекта - это линия, представляющая край формы объекта.Подчеркивание точек контура - Sobel, выделение линий контура - Canny.

Применение1. Распознавание. По контуру можно часто определить тип объекта, который мы наблюдаем.

2. Измерение. С помощью контура можно точно оценить размеры объекта, их поворот и расположение.

http://howto.nicubunu.ro/gears/gears_16.png http://cvpr.uni-muenster.de/research/rack/index.html

Page 30: Open Frameworks и OpenCV

Пример проекта на OpenCV:поиск биллиардного шара

Page 31: Open Frameworks и OpenCV

Задача

На изображении биллиардного поля найти координаты центров биллиардных шаров.

Алгоритм:

1. Пороговой обработкой найти яркие пикселы.2. Анализ областей. Методом заливки найдем связные области,среди них найдем такие, размеры которых допускают, что это шары.

Page 32: Open Frameworks и OpenCV

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

Mat image = imread("C:\\billiard.png"); //загрузка входного изображения imshow( "Input image", image ); vector<Mat> planes; split( image, planes ); Mat gray = 0.299*planes[2] + 0.587*planes[1] + 0.114*planes[0];

double thresh = 50.0; //Порог, подбирается опытным путем threshold( gray, gray, 50.0, 255.0, CV_THRESH_BINARY );

imshow( "Threshold", gray );

Page 33: Open Frameworks и OpenCV

threshold - пример применения

Обратите внимание: мы выделили просто пикселы "не поля". Чтобы найти координаты центров шаров и положение кия - требуется дальнейшая обработка.

Page 34: Open Frameworks и OpenCV

2. Анализ областей

floodFill - выделение связных областей

морфологические операцииdilate - дилатация (*)erode - эрозия (*)

Page 35: Open Frameworks и OpenCV

floodFill - описание

Функция floodFill осуществляет заливку области, начиная из некоторого пиксела (x, y), с заданными границами останова,используя 4- или 8- смежность пикселов.

Важно: она портит исходное изображение - так как заливает его.

1. Чаще всего она применяются для выделения областей, выделенных путем пороговой обработки, для последующего их анализа. 2. Также ее можно использовать для удаления мелких шумов на бинарном изображении (в отличие от способа "эрозия + дилатация" - не портит границы больших областей).

3.Если расширить габаритный бокс найденной области на 1 пиксел со всех сторон и произвести заливку, то таким способом можно устранить внутренние дырки в области.

Page 36: Open Frameworks и OpenCV

floodFill - список параметровОбъявление и описание списка параметров:

int floodFill(Mat& image, Point seed, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4) image - входное изображение, 1- или 3-канальное, 8 или 32-битное. seed - пиксел, с которого начать заливку rect - габаритный прямоугольник найденной области loDiff, upDiff - допустимая разность с соседями (либо - с зародышевым пикселом, если flags |= FLOODFILL_FIXED_RANGE) то есть, новый пиксел valueNew должен удовлетворять value - loDiff <= valueNew <= value + upDiff. flags = 4 или 8 - связность.

Результирующее значение - число пикселов в залитой области.

Page 37: Open Frameworks и OpenCV

floodFill - список параметров

Примечание про типы OpenCV: Point - целочисленная точка с полями int x, y;Rect - целочисленный прямоугольник с полями int x, y, width, height;Scalar - представление цвета, например, Scalar( 255 ) - 1-канальный цвет, Scalar( 255, 255, 255 ) - 3-канальный цвет

Page 38: Open Frameworks и OpenCV

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

const int minRectDim = 25; //макс и мин размеры шаровconst int maxRectDim = 35;

//перебор пикселов изображенияfor (int y=0; y<gray.rows; y++) {for (int x=0; x<gray.cols; x++) { int value = gray.at<uchar>(y, x); if ( value == 255 ) { //если значение - 255, то заливаем //значением 200 Rect rect; //сюда запишется габаритный прямоугольник int count = floodFill( gray, Point( x, y ), Scalar( 200 ), &rect );

Page 39: Open Frameworks и OpenCV

Анализ областей//проверка размера if ( rect.width >= minRectDim && rect.width <= maxRectDim && rect.height >= minRectDim && rect.height <= maxRectDim ) { //центр int x = rect.x + rect.width / 2; int y = rect.y + rect.height / 2; //радиус int rad = ( rect.width + rect.height ) / 4; //рисуем окружность толщиной 2 пиксела circle( image, Point( x, y ), rad, Scalar( 255, 0, 255 ), 2 ); } } } } imshow( "out", image );

Page 40: Open Frameworks и OpenCV

floodFill - пример применения

Page 41: Open Frameworks и OpenCV

Комментарии

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

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

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

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

Page 42: Open Frameworks и OpenCV

Отладка в OpenCV

Для отладки проектов, в которых идет обработка на OpenCV, очень полезна выводить на экран промежуточные изображения с помощью функции imshow

imshow( "image", image );- она выведет изображение image в окно с заголовком "image".

Внимание: 1. нужно #include "highgui.h"2. если выводить изображения в окно с одинаковым именем, на экране будет видно лишь последнее изображение.

Page 43: Open Frameworks и OpenCV

Домашнее задание

Сделать проект на openFrameworks, который1) получает картинку с камеры,

2) затем эта картинка передается в OpenCV, где она- сглаживается- производится пороговая обработка

3) Картинка с камеры и результирующая картинка выводится на экран средствами openFrameworks.