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
  • +1
  • 13 августа 2010, 09:40
  • noonv

Комментарии (6)

RSS свернуть / развернуть
+
0
//
// пример работы с 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;
}
avatar

ns5d

  • 19 августа 2012, 17:44
+
0
У меня второй пример прекрасно работает без cvSetZero
avatar

Evtomax

  • 5 августа 2015, 00:06
+
0
Согласен — этот метод там совсем не обязателен :)
avatar

noonv

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

workss

  • 24 января 2018, 15:05
+
0
Разумеется, статья от 2010 года слегка устарела.
Сейчас, имеет смысл использовать:
cvCopy(src, dst, mask);

или же для С++:
matSrc.copyTo(matDst, mask);
avatar

admin

  • 24 января 2018, 15:16
+
0
Большое спасибо)) Поправил и работает))
avatar

workss

  • 24 января 2018, 17:38

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