例八:ROI(感兴趣区域,region of interesting)的运用
1.cvSetImageROI(IplImage* image,CvRect rect)
功能:设置ROI区域
Rect(x,y,width,height) 参数分别为左上的x,y坐标,区域的宽度、高度
2.cvAddS(const CvArr* scr,CvScalar value,CvArr* dst,const CvArr* mask=NULL)
功能:在图像上附加像素值
参数分别为输入的图像,附加的像素值,输出的图像
其中CvScalar可初始化0-4个通道
举例:
a) 存放单通道图像中像素:cvScalar(255);
b) 存放三通道图像中像素:cvScalar(255,255,255);
3.cvResetImageROI(IplImage* image)
功能:释放基于给定的矩形设置图像的ROI
参数为待处理图像
说明:如果你对图像设置了ROI,那么,Opencv的大多数函数只在该ROI区域内运算(只处理该ROI区域),如果没设ROI的话,就会出来整幅图像。所以一般设置ROI进行处理之后再取消掉ROI,不然只会显示ROI的区域。
例程:
#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
int _tmain(int argc, char** argv)
{
IplImage* src;
if ((src = cvLoadImage("D:\\2.JPG")) != 0){
cvSetImageROI(src,cvRect(85,55,100,100));//设置ROI的区域
cvAddS(src, cvScalar(100), src); //对该区域进行处理
cvResetImageROI(src); //src上的ROI区域取消掉
cvNamedWindow("Roi_Add", 1);
cvShowImage("Roi_Add", src);
cvWaitKey(0);
}
return 0;
}
例九:WidthStep方法
ROI只能串行处理而且必须不断设置和重置。
WidthStep可以设置和保持一幅图像的多个子区域处于活动状态
如果用WidthStep方法对图像进行处理,我们想到的方法是构建一个图像sub_img指针指向图像src中的一部分区域,这样对sub_img进行处理就是对src的一部分进行处理,那么怎么实现呢?
如果我们用cvCreateImage,创建头并分配数据。而用cvCreateImageHeader只是创建空间,并不会初始化空间内的数据.我们既然不需要初始化数据而是让其指向src的一部分,要用cvCreateImageHeader创建一个IplImage*指针,第一个参数即为你想处理的区域的大小(宽度和高度)。
然后要让它其他重要的的参数和原图一致,如:
origin,origin为0表示顶左结构,即图像的原点是左上角,如果为1为左下角
Widthstep,widthStep是指的图片中的每一行占用多少个字节
然后通过指针的传递使sub_img指向src指定的区域,最后进行处理
主要使用的函数如下:
1.cvCreateImageHeader(cvsize(width,height),depth,nchannels)
只用来创建图像头,而没有分配数据。
2.CvRect sub_rect = cvRect(85, 55, 100, 100)
设置一个虚拟的区域,即为要处理的区域,注意这个区域的宽度和高度,即cvRect的第三四个参数,要和创建图像头时定义的宽度和高度相等,因为这两个函数指向的是同一片区域
3.sub_img->imageData = src->imageData + sub_rect.y*src->widthStep + sub_rect.x*src->nChannels;
让sub_img指针指向src中待处理区域,同时由于创建时对sub_img的大小进行了声明,就能实现sub_img即为src上大小为cvRect的一片区域
#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
int main(){
IplImage* src;
if ((src = cvLoadImage("D:\\2.JPG")) != 0){
IplImage* sub_img = cvCreateImageHeader(cvSize(100, 100), src->depth, src->nChannels); //声明一个文件头,指向图像的一部分区域
sub_img->origin = src->origin;
sub_img->widthStep = src->widthStep;
CvRect sub_rect = cvRect(85, 55, 100, 100);//要进行处理的区域
sub_img->imageData = src->imageData + sub_rect.y*src->widthStep + sub_rect.x*src->nChannels; //将创建的图像头和待处理的图像关联,使其指向待处理图像上的一部分
cvAddS(sub_img, cvScalar(100), sub_img);
cvNamedWindow("Roi_Add", 1);
cvShowImage("Roi_Add", src);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&sub_img);
cvDestroyWindow("Roi_Add");
}
}
例十:两张图片的叠加
1.cvAddWeighted(const CvArr* src1,double alpha, const CvArr* src2, double beta,
double gamma, CvArr* dst )
各个变量的意义:
src1 //第一个原数组.
alpha //第一个数组元素的权值
src2 //第二个原数组
beta //第二个数组元素的权值
dst //输出数组
gamma //添加的常数项。
函数 cvAddWeighted 计算两数组的加权值的和:
dst(I)=src1(I)*alpha+src2(I)*beta+gamma
所有的数组必须有相同的类型相同的大小。
我们的图片size不一定一致,这时候就需要用到我们的cvSetImageROI从原图像上选中大小相同的区域进行操作。但是注意选定的区域一定不能比图像的区域要大。
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
int _tmain(int argc, _TCHAR* argv[])
{
IplImage *src1, *src2;
if ((src1 = cvLoadImage("D:\\2.jpg")) != 0 && (src2 = cvLoadImage("D:\\3.jpg")) != 0){
cvSetImageROI(src1, cvRect(50,50,400, 400));
cvSetImageROI(src2, cvRect(0, 0, 400, 400));
cvAddWeighted(src1,0.6,src2,0.4,0.0,src1);//对src1和src2按权重进行叠加
cvResetImageROI(src1);
cvNamedWindow("blend", 0);
cvShowImage("blend", src1);
cvWaitKey(0);
}
return 0;
}