OpenCV学习之子图像操作

我们有时候希望对图像的某个小部分进行操作,而不是对整个图像进行运算。有两种方法,ROI和widthStep。

1. ROI

设置一个ROI区域使用cvSetImageROI,取消一个ROI使用cvResetImageROI。函数原型分别如下:

void cvSetImageROI( IplImage* image, CvRect rect );

void cvResetImageROI( IplImage* image );

rect就是我们要操作的图像的某个区域。实例如下:


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


int main(int argc, char* argv[])
{

IplImage* src;

CvRect rect = cvRect(70, 70, 50, 50); 

if (argc == 2 && ((src = cvLoadImage(argv[1], 1)) != NULL)) {

cvSetImageROI(src, rect);

cvAddS(src, cvScalar(50), src);

cvResetImageROI(src);

cvNamedWindow("roi_add", CV_WINDOW_AUTOSIZE);

cvShowImage("roi_add", src);

cvWaitKey();

cvReleaseImage(&src);

cvDestroyWindow("roi_add");

}

return 0;

}

这里我们将ROI区域的灰度值增加50。


2. widthStep

有了ROI,为什么还需要使用widthStep。ROI只能串行的处理,需要不断设置和重置,而使用widthStep可以连续的操作多个子区域。实例如下:

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


int main(int argc, char* argv[])
{

IplImage* src;

CvRect rect = cvRect(100, 20, 50, 50);

if (argc == 2 && ((src = cvLoadImage(argv[1], 1)) != NULL)) {

IplImage* sub_img = cvCreateImageHeader(cvSize(rect.width, rect.height),

src->depth, src->nChannels);

sub_img->origin = src->origin;

sub_img->widthStep = src->widthStep;


sub_img->imageData = src->imageData +

rect.y * src->widthStep +

rect.x * src->nChannels;


cvAddS(sub_img, cvScalar(50), sub_img);

cvNamedWindow("sub_add", CV_WINDOW_AUTOSIZE);

cvShowImage("sub_add", src);

cvWaitKey();

   

cvReleaseImageHeader(&sub_img);

cvDestroyWindow("sub_add");

cvReleaseImage(&src);


}

return 0;
}

注意:

在这里我们只创建了一个子图像的头,它的数据域在原图像中。我们通过widthStep来操作原图像的数据,从而达到修改原图像子区域的操作。

子图像的widhtStep等于原图像的widthStep,因为操作了一行后,欲操作下一行,必须将数据域指针加上widthStep。

你可能感兴趣的:(image,null)