OpenCV学习笔记05--ROI和WidthStep的运用

例八:ROI(感兴趣区域,region of interesting)的运用

1.cvSetImageROIIplImage* imageCvRect rect

功能:设置ROI区域

Rectx,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.cvResetImageROIIplImage* 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*指针,第一个参数即为你想处理的区域的大小(宽度和高度)。

然后要让它其他重要的的参数和原图一致,如:

originorigin0表示顶左结构,即图像的原点是左上角,如果为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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值