Лекции OpenCV: 4. Работа с каналами, пороговая обработка,...
-
Upload
denis-perevalov -
Category
Documents
-
view
7.138 -
download
13
Transcript of Лекции OpenCV: 4. Работа с каналами, пороговая обработка,...
с/к Анализ изображений, OpenCV
4. Работа с каналами, пороговая обработка, заливка. Пример: поиск биллиардных шаров
УрГУ / ИММ осень 2010лекции и объявления: вопросы отправляйте на адрес www.uralvision.blogspot.com [email protected]
http://www.svi.nl/wikiimg/SeedAndThreshold_02.png
Формат азбуки1. Название функции2. Что она делает3. Для чего она применяется4. Объявление и описание списка параметров5. Пример работы:- работающий код cpp, который считывает изображение, проводит обработку и выдает картинку на экран или пишет в файл с помощью функции imwrite- входная картинка (png или jpg)- результат работы (png или jpg)
Общие операции над изображениями
Общие операции над изображениямиsplit - разбиение на каналы
merge - сшивка каналовresize - изменение размера (*)cvtColor - конвертация цветовых пространств (*)
* - функции для самостоятельного изучения в Практической задаче 1, см. распределение по фамилиям на uralvision.blogspot.com
split и merge - описание
Функция split разбивает многоканальное изображение на каналы.
Функция merge склеивает несколько одноканальных изображений в многоканальное.
Чаще всего они применяются для поканальной обработки цветных изображений, а также для различных манипуляций с каналами.
split и merge - список параметров
Объявление и описание списка параметров: void split ( const Mat& mtx, vector<Mat>& mv ) mtx - исходное цветное изображение mv - результирующий набор 1-канальных изображений
void merge ( const vector<Mat>& mv, Mat& dst ) mv - исходный набор 1-канальных изображений dst - результирующее цветное изображение
split и merge - пример примененияЗадача - на входном цветном изображении обменять местами красный и синий канал, а также рассчитать 1-канальное изображение, представляющее яркость.
Mat image = imread("C:\\abc-blocks.png"); //загрузка входного изображения imshow( "Input image", image );
vector<Mat> planes; split( image, planes ); //разбиение image на три канала planes imshow( "Blue", planes[0] ); imshow( "Green", planes[1] ); imshow( "Red", planes[2] ); vector<Mat> planesIzm( 3 ); //смена Red и Blue местами: planesIzm[0] = planes[2]; planesIzm[1] = planes[1]; planesIzm[2] = planes[0]; Mat imageIzm; merge( planesIzm, imageIzm ); imshow( "Result", imageIzm );
//вычисляем яркость по формуле 0.299*R + 0.587*G + 0.114*B //(Но, вообще-то, это правильней делать с помощью cvtColor) Mat gray = 0.299*planes[2] + 0.587*planes[1] + 0.114*planes[0]; imshow( "Gray", gray );
split и merge - пример применения
split и merge - работа с памятью
1. Осуществляется ли копирование данных при работе со split и merge?
2. В рассмотренном примере - если изменить imageIzm, то изменится ли image?
- Правильный ответ на эти вопросы является Практической задачей 2.
Попиксельные операции
Попиксельные операции
threshold - пороговая обработка
adaptiveThreshold - адаптивная пороговая обработка (*)min, max - минимум, максимум (*)abs - взятие абсолютного значения (*)pow - возведение в степень (*)sqrt - извлечение квадратного корня (*)randu - заполнение случайными значениями (*)
threshold - описание
Функция threshold осуществляет пороговую обработку изображения.
Чаще всего она применяются для выделения пикселов интересующих объектов на изображении.
threshold - список параметровОбъявление и описание списка параметров: double threshold(const Mat& src, Mat& dst, double thresh, double maxVal, int thresholdType) src и dst - исходное и результирующее 1-канальные изображения. Допускается, чтобы dst был равен src. thresh - порог, maxVal - новое максимальное значение (применяется для THRESH_BINARY, THRESH_BINARY_INV ) thresholdType - тип функции пороговой обработки: THRESH_BINARY THRESH_BINARY_INV THRESH_TRUNC THRESH_TOZERO THRESH_TOZERO_INV THRESH_OTSU (- тут порог находится автоматически, и это возвращаемое значение)
threshold - список параметровthresholdType - тип функции пороговой обработки:
THRESH_BINARY
THRESH_BINARY_INV
THRESH_TRUNC
THRESH_TOZERO
THRESH_TOZERO_INV
THRESH_OTSU (- тут порог находится автоматически, и это возвращаемое значение)
threshold - пример примененияЗадача - на изображении бильярдного поля выделить пикселы, не являющиеся полем (условия съемки такие, что поле - темное)
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 );
threshold - пример применения
Обратите внимание: мы выделили просто пикселы "не поля". Чтобы найти координаты центров шаров и положение кия - требуется дальнейшая обработка.
Работа с областями
Работа с областями
floodFill - выделение связных областей
морфологические операцииdilate - дилатация (*)erode - эрозия (*)
floodFill - описание
Функция floodFill осуществляет заливку области, начиная из некоторого пиксела (x, y), с заданными границами останова,используя 4- или 8- смежность пикселов.
Важно: она портит исходное изображение - так как заливает его.
1. Чаще всего она применяются для выделения областей, выделенных путем пороговой обработки, для последующего их анализа. 2. Также ее можно использовать для удаления мелких шумов на бинарном изображении (в отличие от способа "эрозия + дилатация" - не портит границы больших областей).
3.Если расширить габаритный бокс найденной области на 1 пиксел со всех сторон и произвести заливку, то таким способом можно устранить внутренние дырки в области.
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 - связность.
Результирующее значение - число пикселов в залитой области.
floodFill - список параметров
Примечание про типы OpenCV: Point - целочисленная точка с полями int x, y;Rect - целочисленный прямоугольник с полями int x, y, width, height;Scalar - представление цвета, например, Scalar( 255 ) - 1-канальный цвет, Scalar( 255, 255, 255 ) - 3-канальный цвет
floodFill - пример примененияЗадача - на изображении биллиардного полян найти биллиардные шары - то есть. вычислить их центры и размеры. Идея - используя результат примера с 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 );
floodFill - пример применения//проверка размера 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 );
floodFill - пример применения
floodFill - пример применения
В данном примере мы рассмотрели простейший способ нахождения шаров на изображении - путем анализа размеров габаритных прямоугольников. Такой анализ работает в предположении, что на изображении нет других объектов с подобными габаритными прямоугольниками.
Для реального применения, требуется более детальный анализ областей.В первую очередь это связано с тем, что если шары расположены близко друг от друга, то они могут "слипаться" в одну связную область.
Возможные подходы решения такой проблемы: 1. Залить внутренность области, выделить контур полученной области и проанализировать его участки выпуклости и вогнутости для выделения шаров.
2. Использовать шаблон "круг", который прикладывать к найденной области и искать оптимальные его расположения.
Домашнее задание
Практическая задача 1 - см. по фамилии, на uralvision.blogspot.com
Практическая задача 2 - см. в тексте про split и merge.