1. OpenCV шаг за шагом. Введение.
2. Установка.
3. Hello World.
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения
13. Типы данных OpenCV
14. Матрица
15. Сохранение данных в XML
16. Генерация случайных чисел
17. Обработка изображения — морфологические преобразования
18. Обработка изображения — морфологические преобразования 2
19. Обработка изображения — заливка части изображения
cvFloodFill() — полезная функция, если требуется пометить или изолировать область изображения для дальнейшего анализа. Т.е. эта функция реализует заливку области, что наводит на мысли об аналогичных инструментах в графических редакторах 🙂
CVAPI(void) cvFloodFill( CvArr* image, CvPoint seed_point, CvScalar new_val, CvScalar lo_diff CV_DEFAULT(cvScalarAll(0)), CvScalar up_diff CV_DEFAULT(cvScalarAll(0)), CvConnectedComp* comp CV_DEFAULT(NULL), int flags CV_DEFAULT(4), CvArr* mask CV_DEFAULT(NULL));
— заполняет связанную область заданным цветом. Начиная с заданной начальной точки и далее, определяя принадлежность области по близости значений соседних пикселей.
image — входное изображение (1- или 3-канальное), 8-битное или 32F. Изображение модифицируется функцией, если не установлен флаг CV_FLOODFILL_MASK_ONLY
seed_point — начальная точка
new_val — новое значение пикселей
lo_diff — максимальное нижнее значение разницы в яркости/цвете между наблюдаемым пикселем и одним из его соседей, чтобы добавить его в область. В случае 8-битного цветного изображения — это упакованное значение.
up_diff — максимальное верхнее значение разницы в яркости/цвете между наблюдаемым пикселем и одним из его соседей, чтобы добавить его в область. В случае 8-битного цветного изображения — это упакованное значение.
comp — указатель на структуру CvConnectedComp, которую заполняет функция, возвращая в неё информацию о заполненной области:
typedef struct CvConnectedComp { double area; /* площадь */ CvScalar value; /* усреднённый цвет области */ CvRect rect; /* ROI - область интереса */ CvSeq* contour; /* граница */ } CvConnectedComp;
flags — флаг операции. Младшие биты содержат значение связности — 4(по-умолчанию) или 8, используемое функцией. Связность определяет сколько соседей пикселя обрабатываются. Старшие биты могут быть 0 или комбинацией флагов:
#define CV_FLOODFILL_FIXED_RANGE (1 << 16) #define CV_FLOODFILL_MASK_ONLY (1 << 17)
CV_FLOODFILL_FIXED_RANGE - если установлен, используется разница между текущим пикселем и начальным пикселем, в противном случае - используется разница между соседними пикселями (плавающий диапазон)
CV_FLOODFILL_MASK_ONLY - если установлен, то функция не вносит изменений в изображение, но заполняет маску (которая, в данном случа, должна быть отлична от NULL )
mask - маска операции, 1-канальное 8-битное изображение, на 2 пикселя шире и длинее, чем изображение. Если отлично от NULL, то функция использует и обновляет маску. Заполнение не будет идти поверх ненулевых пикселей маски. Например, детектор границ может использоваться в качестве маски для остановки заливки на границах. Возможно использование одной маски в нескольких вызовах функции, для уверенности, что заполненные области не перекроются.
! NB: т.к. маска больше, чем изображение - пиксель маски, соответствующий пикселю (x,y) изображения, имеет координаты (x+1, y+1)
// // пример использования функции cvFloodFill() // для заливки области // начальный пиксель области выбирается по клику мышкой // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> // заливка области картинки цветом void fill(IplImage* src, CvPoint seed, CvScalar color=CV_RGB(255, 0, 0)) { assert(src); CvConnectedComp comp; cvFloodFill( src, seed, color, cvScalarAll(10), // минимальная разность cvScalarAll(10), // максимальная разность &comp, CV_FLOODFILL_FIXED_RANGE + 8, 0); // покажем площадь заливки printf("[filled area] %.2f\n", comp.area); } // обработчик событий от мышки void myMouseCallback( int event, int x, int y, int flags, void* param ) { IplImage* img = (IplImage*) param; switch( event ){ case CV_EVENT_MOUSEMOVE: break; case CV_EVENT_LBUTTONDOWN: printf("%d x %d\n", x, y); // вызываем нашу функцию-обёртку вокруг cvFloodFill() fill(img, cvPoint(x, y)); break; case CV_EVENT_LBUTTONUP: break; } } int main(int argc, char* argv[]) { IplImage *src=0, *dst=0; // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку src = cvLoadImage(filename, 1); printf("[i] image: %s\n", filename); assert( src != 0 ); // покажем изображение cvNamedWindow( "original", 1 ); // вешаем обработчик мышки cvSetMouseCallback( "original", myMouseCallback, (void*) src); while(1){ // показываем картинку cvShowImage( "original", src ); char c = cvWaitKey(33); if (c == 27) { // если нажата ESC - выходим break; } } // освобождаем ресурсы cvReleaseImage(&src); cvReleaseImage(&dst); // удаляем окна cvDestroyAllWindows(); return 0; }
Пример работы функции при клике в верхнем левом углу и установленном флаге CV_FLOODFILL_FIXED_RANGE. Если же этот флаг убрать, то при той же начальной точке будет закрашена почти вся картинка.
Читать далее: 20. Обработка изображения — альфа-смешивание
0 комментариев на «“19. OpenCV шаг за шагом. Обработка изображения — заливка части изображения”»
IplImage *src=0, *dst=0;
*dst — походу лишние.:)
Привет! Спасибо за классные уроки.
А есть ли способ обнаружить на картинке все пиксели заданного цвета, с некоторой разницей яркости, и изменить их цвет на другой?
Спасибо.
тут должен помочь шаг №23. OpenCV шаг за шагом. Поиск объекта по цвету. Цветовое пространство HSV. 🙂
Уроки супер, спасибо огромное!!! Вопрос, как сделать так, что бы при новом нажатии ЛКМ старая область затиралась?
рисовать не на оригинальном изображении, а на его копии, которую обновлять при следующем нажатиии.
Помогите, пожалуйста, вопрос такой:
компилятор ругается на функцию fill(img, cvPoint(x, y));
Якобы ‘fill’: identifier not found
Нигде на просторах Вселенной не смогла найти ответ на эту загадку)
Возможно компилятору не нравится, что нет объявления функции — можно попробовать добавить его после includ-ов.