12. OpenCV шаг за шагом. ROI — интересующая область изображения


1. OpenCV шаг за шагом. Введение.
2. Установка.
3. Hello World.
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения


ROI (Region Of Interest — регион интересов — интересующая область изображения) — один из фундаментов OpenCV.
ROI позволяет пользователю задать определённую прямоугольную область изображения (т.е. ROI всегда должна находится внутри исходного изображения).
Почти все функции должны поддерживать работу с ROI, т.е. работу с выделенной областью изображения, что полезно для ускорения работы алгоритмов. Т.о. если нас интересует только определённая область изображения — можно её выделить и работать только с ней, не затрагивая всё изображение целиком.

Вот какие функции для работы с ROI предоставляет OpenCV:

CVAPI(void)  cvSetImageROI( IplImage* image, CvRect rect );

— установка интересующей области рисунка (COI не меняется)
image — указатель на изображение
rect — прямоугольник интересующей области

CVAPI(void)  cvResetImageROI( IplImage* image );

— сбрасывает область интересов (и COI)
image — указатель на изображение

CVAPI(CvRect) cvGetImageROI( const IplImage* image );

— возвращает область интересов изображения
image — указатель на изображение
Если ROI не установлена функция вернёт cvRect(0,0,image->width,image->height)

ROI можно использовать для вырезания части изображения или, наоборот, добавления изображения.

Пример работы с ROI — программа загружает изображение и по заданным координатам устанавливает ROI с помощью функции cvSetImageROI(). Затем вызывается функция cvAddS(), которая добавляет к элементам массива (пикселям изображения) заданную скалярную величину. Результатом является цветовое выделение квадрата ROI.

//
// пример работы с ROI
//

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

IplImage* image = 0;

int main(int argc, char* argv[])
{
	// имя картинки задаётся первым параметром
	char* filename = argc >= 2 ? argv[1] : "Image0.jpg";
	// получаем картинку
	image = cvLoadImage(filename,1);

	printf("[i] image: %s\n", filename);
	assert( image != 0 );

	cvNamedWindow("origianl", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("ROI", CV_WINDOW_AUTOSIZE);  

	// задаём ROI
	int x = argc >= 3 ? atoi(argv[2]) : 40;
	int y = argc >= 4 ? atoi(argv[3]) : 20;
	int width = argc >= 5 ? atoi(argv[4]) : 100;
	int height = argc >= 6 ? atoi(argv[5]) : 100;
	// добавочная величина 
	int add =  argc >= 7 ? atoi(argv[6]) : 200;

	cvShowImage( "origianl", image);
	// устанавливаем ROI
	cvSetImageROI(image, cvRect(x,y,width,height));
	cvAddS(image, cvScalar(add), image);
	// сбрасываем ROI
	cvResetImageROI(image);
	// показываем изображение
	cvShowImage("ROI", image);

	// ждём нажатия клавиши
	cvWaitKey(0);

	// освобождаем ресурсы
	cvReleaseImage( &image );
	cvDestroyAllWindows(); 
	return 0;
}

CVAPI(void)  cvAddS( const CvArr* src, CvScalar value, CvArr* dst,
                     const CvArr* mask CV_DEFAULT(NULL));

— рассчёт сумма массива и скаляра (скаляр добавляется к каждому элементу массива)
формула:

	dst(I)=src(I)+value if mask(I)!=0

src — исходный массив
value — скаляр для суммирования
dst — массив для сохранения результата
mask — маска (8-битный 1-канальный массив, определяющий какие элементы массива подлежат изменению)

А вот другой, более наглядный пример работы с ROI:
Программа принимает 4 параметром название изображения, которое накладывается в ROI область первого изображения.
Для этого область интересов сначала обнуляется с помощью cvZero(), а затем туда копируется содержимое массива второго изображения при помощи cvCopyImage().

//
// пример работы с ROI 2
// вывод в ROI другого изображения
//

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

IplImage* image = 0;
IplImage* src = 0;

int main(int argc, char* argv[])
{
	// имя картинки задаётся первым параметром
	char* filename = argc >= 2 ? argv[1] : "Image0.jpg";
	// получаем картинку
	image = cvLoadImage(filename,1);

	printf("[i] image: %s\n", filename);
	assert( image != 0 );

	cvNamedWindow("origianl", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("ROI", CV_WINDOW_AUTOSIZE);  

	// задаём ROI
	int x = argc >= 3 ? atoi(argv[2]) : 120;
	int y = argc >= 4 ? atoi(argv[3]) : 50;
	// добавочное изображение
	char* filename2 = argc >= 5 ? argv[4] : "eye.jpg";
	src = cvLoadImage(filename2,1);
	assert( src != 0 );

	// размер ROI
	int width = src->width;
	int height = src->height;

	cvShowImage( "origianl", image);
	// устанавливаем ROI
	cvSetImageROI(image, cvRect(x,y,width,height));

	// обнулим изображение
	cvZero(image);

	// копируем изображение
	cvCopyImage(src, image);

	// сбрасываем ROI
	cvResetImageROI(image);
	// показываем изображение
	cvShowImage("ROI", image);

	// ждём нажатия клавиши
	cvWaitKey(0);

	// освобождаем ресурсы
	cvReleaseImage( &image );
	cvReleaseImage( &src );
	cvDestroyAllWindows(); 
	return 0;
}

Вот видите, как здорово? Всего несколько строчек кода, а у меня уже открылся третий глаз 🙂
Крррасота!

CVAPI(void)  cvSetZero( CvArr* arr );
#define cvZero  cvSetZero

— очищает все элементы массива arr (устанавливает их в 0)

Далее: 13. Типы данных OpenCV


6 комментариев на «“12. OpenCV шаг за шагом. ROI — интересующая область изображения”»

    • Согласен — этот метод там совсем не обязателен 🙂

  1. Мне кажется или статья слегка устарела? На:
    cvCopyImage(src, image);
    Ругается:
    Ошибка C3861 cvCopyImage: идентификатор не найден…
    Проблемм с openCv нету- все остальные работают)

    • Разумеется, статья от 2010 года слегка устарела.
      Сейчас, имеет смысл использовать:

      cvCopy(src, dst, mask);

      или же для С++:

      matSrc.copyTo(matDst, mask);
    • Большое спасибо)) Поправил и работает))

  2. //
    // пример работы с ROI 2
    // вывод в ROI другого изображения
    //
    
    #include <cv.h>
    #include <highgui.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    IplImage* image = 0;
    IplImage* src = 0;
    
    int main(int argc, const char* argv[]) {
    	// имя картинки задаётся первым параметром
    	const char* filename = argc >= 2 ? argv[1] : "Image0.jpg";
    	// получаем картинку
    	image = cvLoadImage(filename,1);
    
    	printf("[i] image: %s\n", filename);
    	assert(image != 0);
    
    	cvNamedWindow("origianl", CV_WINDOW_AUTOSIZE);
    	cvNamedWindow("ROI", CV_WINDOW_AUTOSIZE);
    
    	// задаём ROI
    	int x = argc >= 3 ? atoi(argv[2]) : 120;
    	int y = argc >= 4 ? atoi(argv[3]) : 120;
    
    	const char* filename2 = argc >= 5 ? argv[4] : "eye.jpg";
    	// добавочное изображение
    	// устанавливаем ROI
    	int rx = 95;
    	int ry = 195;
    	int rdx = 45;
    	cvSetImageROI(image, cvRect(rx, ry, rdx, rdx));
    	cvSaveImage("eye.jpg", image);
    
    	src = cvLoadImage(filename2,1);
    	assert(src != 0);
    
    	// размер ROI
    	int width = src->width;
    	int height = src->height;
    
    	cvShowImage("origianl", image);
    	// устанавливаем ROI
    	cvSetImageROI(image, cvRect(x,y,width,height));
    
    	// обнулим изображение
    	cvZero(image);
    
    	// копируем изображение
    	cvCopyImage(src, image);
    
    	// сбрасываем ROI
    	cvResetImageROI(image);
    	// показываем изображение
    	cvShowImage("ROI", image);
    
    	// ждём нажатия клавиши
    	cvWaitKey(0);
    
    	// освобождаем ресурсы
    	cvReleaseImage(&image);
    	cvReleaseImage(&src);
    	cvDestroyAllWindows();
    	return 0;
    }

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

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
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение