OpenCV doesn't provide a function to make non-rectangle ROI, so I use image mask to do the trick. It works like this. say we have two images:
img
- an RGB image.mask
- a black image, with white circle on it. We can extract a region from img
by:
res = img & mask
res
now contains a portion from img
where the white circle is located.
The full listing is shown below. The code loads an image, select circular ROI, and applying some processing on it.
Listing 1: Extract a circular ROI
#include "cv.h"
#include "highgui.h"
int
main(
int
argc,
char
** argv)
{
IplImage* src, * res, * roi;
/* usage: <prog_name> <image> */
if
(argc < 2)
{
fprintf
(stderr,
"Usage: %s <image>\n"
, argv[0]);
return
1;
}
src = cvLoadImage(argv[1], 1);
res = cvCreateImage(cvGetSize(src), 8, 3);
roi = cvCreateImage(cvGetSize(src), 8, 1);
/* prepare the 'ROI' image */
cvZero(roi);
/* Note that you can use any shape for the ROI */
cvCircle(
roi,
cvPoint(130, 100),
50,
CV_RGB(255, 255, 255),
-1, 8, 0
);
/* extract subimage */
cvAnd(src, src, res, roi);
/*
* do the main processing with subimage here.
* in this example, we simply invert the subimage
*/
cvNot(res, res);
/* 'restore' subimage */
IplImage* roi_C3 = cvCreateImage(cvGetSize(src), 8, 3);
cvMerge(roi, roi, roi, NULL, roi_C3);
cvAnd(res, roi_C3, res, NULL);
/* merge subimage with original image */
cvNot(roi, roi);
cvAdd(src, res, res, roi);
/* show result */
cvNamedWindow(argv[1], 1);
cvNamedWindow(
"res"
, 1);
cvShowImage(argv[1], src);
cvShowImage(
"res"
, res);
cvWaitKey(0);
/* be tidy */
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&res);
cvReleaseImage(&roi);
return
0;
}
|
In the example above, I only invert the subimage to make it simple. Change the line 39 with more complex image processing.
IplImage *src,*res,*roi;
src = cvLoadImage("test.bmp",1);
res = cvCreateImage(cvGetSize(src),8,3);
roi = cvCreateImage(cvGetSize(src),8,1);
cvNamedWindow("res");
cvNamedWindow("roi");
cvNamedWindow("src");
cvNamedWindow("roi_c3");
//prepare the 'ROI' image
cvZero(roi); //black
cvShowImage("roi",roi);
//NOte that you can use any shape for the ROI
cvCircle(roi,cvPoint(130,100),50,CV_RGB(255,255,255),-1,8,0);
//Extract subimage
cvAnd(src,src,res,roi);
//do the main processing with subimage here
//in this example, we simply invert the subimage
cvNot(res,res);
//restore subimage
IplImage *roi_c3 = cvCreateImage(cvGetSize(src),8,3);
cvMerge(roi,roi,roi,NULL,roi_c3);
cvAnd(res,roi_c3,res,NULL);
//merge subimage with original image
//cvNot(roi,roi);
//cvAnd(src,res,res,NULL);
cvAnd(src,roi_c3,res,NULL);
//show result
cvShowImage("roi_c3",roi_c3);
cvShowImage("src",src);
cvShowImage("roi",roi);
cvShowImage("res",res);
//Show_picture("test.bmp",(CStatic*)GetDlgItem(IDC_STATIC_PIC));
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&res);
cvReleaseImage(&roi);
cvReleaseImage(&roi_c3);