OpenCV_lection03_2012

Post on 30-Oct-2014

3.205 views 0 download

Tags:

Transcript of OpenCV_lection03_2012

с/к Обработка информации, осень 20133. Сглаживание изображений.

Выделение контуров. Получение кадров с камеры.

Геометрическое выравнивание изображений

www.uralvision.blogspot.com perevalovds@gmail.com УрФУ / ИММ УрО РАН

Денис Сергеевич Перевалов

Сглаживание изображенийСамая часто используемая функция для сглаживания:

void GaussianBlur(const Mat& src, //входное изображение Mat& dst, //выходное изображение Size ksize, //размер окна сглаживания double sigmaX, //параметры гауссиана double sigmaY=0, int borderType=BORDER_DEFAULT) //как работать с //границей

- Функция выполняет сглаживание src с использованием функции Гаусса.- dst будет иметь тот же тип и размеры, что и src.- Допустимо, чтобы dst == src.- ksize - размер ядра фильтра, когда размеры должны быть нечетными.- sigmaX, sigmaY - стандартные отклонения по X и Y. Если 0, то вычисляются из ksize.- borderType - как работать на границе, например, BORDER_REFLECT.

Сглаживание изображенийПримерMat image = imread( "3dart.jpg" );Mat blurred1, blurred2;GaussianBlur( image, blurred1, cv::Size( 11, 11 ), 0 );GaussianBlur( image, blurred2, cv::Size( 41, 41 ), 0 );

image blurred1 blurred2

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

Сглаживание изображенийДругие функции, выполняющие сглаживание:medianBlur - медианная фильтрацияblur - сглаживание квадратным окном (усреднение)

filter2D - сглаживание с любым фильтром, представленным в виде матрицы

GaussianBlur medianBlur blur

Все три метода работали с фильтром размером 11x11 пикселов. Гауссов фильтр дал самый естественный результат. Медианный - выделил области одного цвета и удалил мелкие детали.Фильтр усреднения - видны нежелательные артефакты - квадратные края у объектов.

Для чего применяется сглаживание

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

Чаще всего - используют гауссов фильтр, реже - медианную фильтрацию.

Для чего применяется сглаживание2. Устранение неоднородности фона. Применяется гауссов фильтр большого размера, и из исходной картинки вычитается это сглаженное изображение.

В примере использована картинка, полученная инвертированием http://www.eyesontutorials.com/images/Designing/Jeka/tut180_dark_wallpaper/12.jpg

Исходная картинкас неоднородным фоном

Сглаживание фильтром размером 201x201 пиксел

Разность исходной и сглаженной картинок. Фон теперь однородно черный.

Для чего применяется сглаживание

3. Подчеркивание пикселов контуров объектов. (Факт из теории: разность двух гауссианов аппроксимирует лапласиан).Используется два гауссовых фильтра с размерами a и ~2a.

Исходное изображение Разность двух сглаженных картинок с радиусами 3 и 7, умноженная на 20. Ярким цветом выделились контура объектов.

Для чего применяется сглаживание4. Не относящееся к компьютерному зрению,а к компьютерной графике:

- гауссовым фильтром моделируется эффект дефокусировки.

- несимметричным фильтром создается эффект "скоростного смаза" (motion blur).

Боковое движение Движение вперед Вращение

Практическая задача 2 (вариант 1)

Сделать мультфильм, в котором исходная картинка подвергается размытию с возрастающим размером окна. То есть, постепенно размывается.

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

2. Для алгоритма размытия используйтегауссов фильтр (если ваша фамилия четной длины),или медианный фильтр (если ваша фамилия нечетной длины).

3. В мультфильме должно быть не менее 100 кадров.

4. Результат - высылайте ссылку на ваше видео на youtube, и cpp-код.

Уточнение, как делать

В OpenCV есть возможность явно создавать avi файлы. Мы предлагаем сделать проще.

1. Изображения записывать на диск в одну папку в формате .bmp, с названиямиimage000.bmp, image001.bmp, ....

2. Затем из них сделать avi-файл с помощью программы VirtualDub(File->Open video file, и в появившемся диалоге указать первую картинку из набора.После этого Video -> Compresson, выбрать кодек.Наконец, File -> Save as avi... - запись avi-файла).

3. Выложить полученный файл на youtube.

Практическая задача 2 (вариант 2)Используя1) вырезание части изображения, (см. "Работа с прямоугольными подобластями изображения")2) функцию изменения размера resize()3) суммирование изображений с весами (см. "Линейные операции над изображениями")

реализовать эффект "Движение вперед".

Результат представить в виде cpp-файла, а также входной и выходной картинок.Название объекта на входной картинке должно начинаться на первую букву вашей фамилии.

Уточнение, как делать

Вырезаем N=20 прямоугольных областей - image[i], их увеличиваем в размере,и из них строим сумму

1.0 / N * image[0] + 1.0 / N * image[1] + ... + 1.0 / N * image[N-1];

это и будет результат.

Выделение контуров

http://howto.nicubunu.ro/gears/gears_16.png

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

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

Для указания внутренних контуров нужна 3d модель объекта. В этом случае контурами будут проекции на изображение линий изгиба 3d объекта.

http://cvpr.uni-muenster.de/research/rack/index.html

Внешний контур

Внутренний контур

Понятие контураЕсли дано изображение, на котором надо выделить контуры,но нет ни разбиения на области, ни 3d-модели, то возникают неоднозначности определения, что такое контур,

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

Считать ли куст объектом, и искать только его контур, или объектами считать отдельные листья?

Понятие контураПоэтому в машинном зрении часто рассматривают задачу не поиска контуров объектов, а поиск контуров на изображении.

Контур на изображении - это линия, вдоль которой наблюдается скачок по яркости или цвету.

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

Зачем нужно находить контур

1. Распознавание

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

2. Проведение измерений

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

Поиск точек контура

Фильтр Собела

Для подчеркивания точек контуров чаще всего применяют фильтр Собела.

void Sobel(const Mat& src, //входное изображение Mat& dst, //выходное изображение, размер и каналов - как у src int ddepth, //глубина результата, например, CV_32F int xorder, //порядок производной по x int yorder, //порядок производной по y int ksize=3, //размер окна: 1, 3, 5, 7 double scale=1, double delta=0, //масштабирование и сдвиг результата int borderType=BORDER_DEFAULT) //работа с границей

Фильтр осуществляет Гауссово сглаживание и взятие частных производных 1, 2, 3 порядка или смешанных ( xorder по x, yorder по y). (Гауссово сглаживание позволяет получить результат, устойчивый к шумам на изображении.)

Фильтр СобелаПример Mat image = imread( "lodka.jpg" ); //Загрузить изображение с диска

imshow( "image", image ); //Показать изображениеMat imageDX, imageDY;Sobel( image, imageDX, CV_32F, 1, 0, 3, 1.0 / 255.0 ); //производная по xSobel( image, imageDY, CV_32F, 0, 1, 3, 1.0 / 255.0 ); //производная по y

Обратите внимание, что показаны только положительные значения. Отрицательные и нулевые значения - показаны черным цветом.

Фильтр СобелаПример, продолжение

Если трансформировать картинки в серый цвет и взять sqrt( imageDX^2 + imageDY^2 ) - получим подчеркивание точек контура.Применив к ним пороговую обработку, получим набор точек контура. Mat grayX, grayY;

cvtColor( imageDX, grayX, CV_RGB2GRAY );cvtColor( imageDY, grayY, CV_RGB2GRAY );pow(grayX, 2, grayX);pow(grayY, 2, grayY);

Mat contImg = grayX + grayY;sqrt(contImg, contImg);contImg.convertTo( temp, CV_8UC3, 255.0 );

Mat binary;threshold( contImg, binary, 0.7, 1.0, CV_THRESH_BINARY );

Фильтр СобелаПример, продолжение

Другие фильтры подчеркивания точек контура1. Scharr() , 2. Laplacian(), 3. разность двух Гауссианов (см. в лекции про сглаживание).

Все они работают по принципу, аналогичному методу Собела.

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

Решение: использовать алгоритм Канни.

Детектор краев Канни

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

Использует метод двух порогов.

Идея - трассировать контур, двигаясь вдоль точек с максимальным значением "контура".

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

Детектор краев Канниvoid Canny( const Mat& image, //входное изображение, 1-канальное, 8-битное Mat& edges, //выходное изображение double threshold1, //пороги, наибольший - для зародышей контура, double threshold2, //наименьший - для склейки контуров int apertureSize=3, //окно для фильтра Собела bool L2gradient=false //использовать ли евклидову длину вектора //производных Собела, sqrt( dx*dx + dy * dy), //или просто |dx| + |dy| );

Детектор краев КанниПример Mat imageGray, edges;

cvtColor( image, imageGray, CV_RGB2GRAY );Canny( imageGray, edges, 230, 150 );

Исходная картинка Собел + пороговая обработка Детектор краев Канни

Векторизация контуров

Трассировка контура

Трассировка контура - это построение по набору пикселов ломаной, т.е. построение векторного представления контура.

Векторное представление удобно с точки зрения последующей обработки и анализа контура:

- сглаживание и прореживание.- модификация (поворот, растяжение).- сопоставление, анализ и распознавание объектов по их контурам.

Трассировка контуровvoid findContours(const Mat& image, //Входное изображение, //1-канальное, 8-битное //трактуется как бинарное (0 и не 0) vector<vector<Point> >& contours, //Найденные контуры int mode, //Режим поиска контуров int method, //Способ аппроксимации контуров Point offset=Point() //Сдвиг всех результрующих контуров )

Значения mode: CV_RETR_EXTERNAL - только внешние контуры,CV_RETR_LIST - список всех контуровИспользуется другая форма функции, см. документацию:CV_RETR_CCOMP - 2-уровневая иерархия - внешние границы и границы дырок, CV_RETR_TREE - стоит дерево вложенных контуров,

Значения method:CV_CHAIN_APPROX_NONE - без аппроксимацииCV_CHAIN_APPROX_SIMPLE - выбрасявает горизонтальные и вертикальные точки внутри отрезковCV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS - аппроксимация методом Teh-Chin

Трассировка контуровПример vector<vector<Point> > contours;

findContours( edges, contours, CV_RETR_LIST, CV_CHAIN_APPROX_TC89_L1 );

Mat draw = image.clone();drawContours( draw, contours, -1, Scalar( 255, 0, 0 ) );imshow( "find cont", draw );

Анализ контуров

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

Также, статистические моменты и преобразование Фурье и алгоритмы прямого сопоставления контуров.

Проблемы

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

Получение кадров с камеры.Геометрическое выравнивание

изображений

Получение кадров с камерыVideoCapture capture; //Класс для работы с камерами и видеофайламиcapture.open( 0 ); //открыть первую камеру (нумерация с 0)//а если задать строку VideoCapture capture.open( "myfile.avi" ); - будет читать avi-файл

if ( !capture.isOpened() ) { //если камеры нет, завершаем работуcout << "Нет камеры" << endl;return -1;

} Mat image, smoothed, edges;for(;;) { capture >> image; // получение кадра cvtColor(image, smoothed, CV_BGR2GRAY);

GaussianBlur(smoothed, smoothed, Size(7,7), 1.5, 1.5 ); Canny(smoothed, edges, 0, 30, 3 );

imshow( "image", image );imshow("edges", edges);

if(waitKey(30) >= 0) break; //ждем нажатия клавиши 30 мсек, если нажали - выход }

//Деструктор capture сам выключит камеруreturn 0;

Получение кадров с камеры

Геометрическое выравнивание изображений

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

Исходное изображение Изображение с выделенными калибровочными точками

(углы красного 4-угольника)

Результат выравнивания изображения

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

В простейшем случае это просто 4 точки, указывающие, куда должны перейти углы изображения (A,B,C,D) -> [0,w] x [0,h]Примечание: координаты могут быть вещественными числами, что позволяет повысить точность результата.

Матрица проективного преобразования M - размер 3x3, осуществляет преобразование по правилу(x,y) -> M *(x,y,1)

2. C помощью функции getPerspectiveTransform вычисляется оптимальная матрица перспективного преобразования. Реализация OpenCV использует в точности 4 точки.

3. Наконец, данная матрица подставляется в функцию warpPerspective для получения калиброванного изображения.

T

const int K = 4; //будем использовать 4 точки. cv::Point2f src[K]; //координаты точек на изображенииcv::Point2f dst[K]; //координаты результирующих точек

src[ 0 ] = cv::Point2f( ..., ... ); //координаты углов A,B,C,D на изображенииsrc[ 1 ] = cv::Point2f( ..., ... ); //должны идти по часовой стрелке с левого верхнего углаsrc[ 2 ] = cv::Point2f( ..., ... ); //- в соответствии с dst, см. нижеsrc[ 3 ] = cv::Point2f( ..., ... );

dst[ 0 ] = cv::Point2f( 0, 0 ); //результирующие точки; w и h - размеры результатаdst[ 1 ] = cv::Point2f( w, 0 ); dst[ 2 ] = cv::Point2f( w, h );dst[ 3 ] = cv::Point2f( 0, h );

Mat transform = getPerspectiveTransform( src, dst ); //вычисляем матрицу преобразованияwarpPerspective( image, imageResult, transform, cv::Size( w, h ), INTER_LINEAR );//получаем по входному изображению image результат - imageResult

y

x0

h

AB

C

D

wW

H

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

точка (x,y) из [0,1]x[0,1] переводится в 4-угольник с углами A,B,C,D по формуле:

bilinear( x,y ) = (1-x)(1-y) A + x(1-y) B + (1-x)y C + xy D

y

x0

1

1

(x,y)

AB

C

D

a b

cd

Для прямоугольника произвольного размера [0,w] x [0,h]:

bilinear( x, y; w, h ) = bilinear( x / w, y / h )

Данное преобразование можно делать в OpenCV попиксельно, но результат будет не очень гладкий (алиасинг).

Гладкого результата при деформации изображений можно добиться путем использования функции remap.Эта функция позволяет указать, куда должен перейти каждый пиксель изображения, и осуществляет это преобразование:

result( x, y ) = image( tx( x, y ), ty( x, y ) ),

здесь tx, ty - преобразования координат.Важно: remap делает “обратное преобразование”, поэтому его не так просто применить например для реализации билинейного преобразования(- так как там нужно бы result( tx(x,y), ty( x, y ) ) = image( x, y ). )

Подробнее про функцию remap:http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/remap/remap.html )

Практическая задача 3 1. В программу загружается изображение размером w x h пикселей.

2. Пользователь мышью задает 4 точки на изображении A,B,C,D.

3. Программа с помощью перспективного преобразования строит выровненное изображение (A,B,C,D) -> [0,w] x [0,h]и сохраняет его в файл.

4. Программа с помощью билинейного преобразования (попиксельно) строит выровненное изображение[0,w] x [0,h] -> (A,B,C,D)и сохраняет его в файл.