19. OpenCV шаг за шагом. Обработка изображения — заливка части изображения


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 шаг за шагом. Обработка изображения — заливка части изображения”»

  1. Привет! Спасибо за классные уроки.
    А есть ли способ обнаружить на картинке все пиксели заданного цвета, с некоторой разницей яркости, и изменить их цвет на другой?
    Спасибо.

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

  2. Помогите, пожалуйста, вопрос такой:
    компилятор ругается на функцию fill(img, cvPoint(x, y));
    Якобы ‘fill’: identifier not found
    Нигде на просторах Вселенной не смогла найти ответ на эту загадку)

    • Возможно компилятору не нравится, что нет объявления функции — можно попробовать добавить его после includ-ов.

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение