opencv学习笔记(十五)利用cvSetImageROI()对图像部分区域进行操作

来源:互联网 发布:php 验证手机 编辑:程序博客网 时间:2024/05/17 02:26

这是一个对图像部分区域进行操作的程序:

#include "cv.h"#include"highgui.h"int main(int argc, char** argv) {IplImage* src = cvLoadImage("a.jpg");int x = 150;int y = 150;int width = 200;int height = 200;int add = 150;cvSetImageROI(src, cvRect(x, y, width, height));cvAddS(src, cvScalar(add), src);cvResetImageROI(src);cvNamedWindow("ROI", 1);cvShowImage("ROI", src);cvWaitKey(0);return(0);}

15.1cvSetImageROI()

定义:
void cvSetImageROI(IplImage* image,cvRect rect);
但是函数里的参数必须写成cvRect rect,而不是CvRect rect。

15.2CvRect结构:

OpenCV里面的基本数据类型
功能: 包含4个数据成员,x,y,width,height,通过定义矩形左上角坐标和矩形的宽和高来确定一个矩形。
typedef struct CvRect
  {
  int x; /* 方形的左上角的x-坐标 */
  int y; /* 方形的左上角的y-坐标*/
  int width; /* 宽 */
  int height; /* 高 */
  }
x,y用来确定区域左上角的坐标
width和height为矩形区域的宽和高

15.3cvAddS()

定义:
void cvAddS(const CvArr* scr,CvScalar value,CvArr* dst,const CvArr* mask=NULL)
作用:
一个数组和一个标量的元素级的相加运算。
把scr的元素与常量value相加放到dst里。
如果mask没有被设为NULL,那么mask中非零元素指定的dst元素值在函数执行后不变。
参数:
src
原数组
value
被加入数量
dst
输出数组
mask
操作的复盖面(8-bit单通道数组) ; 只有复盖面指定的输出数组被修改
结合下面的mask的说明,应该就是:
如果传递给src的数组是图像类型的,那么将使用ROI或者COI。src数组和dst数组必须具有相同的数据类型、一致的数组维数、一样的大小。
——所以程序里面才是cvAddS(src, cvScalar(add), src);
这两个数组是同一个,所以是“相同的数据类型、一致的数组维数、一样的大小”。

然后,mask = NULL 意思就是没有模板、不使用掩码操作,函数该干啥就干啥。
函数里默认是CvArr* mask=NULL,所以是函数执行本来功能——一个数组和一个标量的元素级的相加运算。
CvScalar就是一个包含四个元素的结构体变量。

15.3.1mask
详细解释参见下面的博客:
http://www.xuebuyuan.com/846166.html
百度得:掩码是一串二进制代码对目标字段进行按位与运算,屏蔽当前的输入位。
//掩码操作,mask是一个8位单通道的数组;mask指定了目标数组(dst)中那些元素是可以改变的
dst(I) = src(I) if mask(I) != 0.
就是说,如果mask不是NULL,也就是说mask是一个数组,并且是一个和dst或src大小完全一致的数组。
这时遍历src的每一个元素,
(1)在位置i时候如果mask对应的值为不为0,那么把src (i) 的值复制给dst (i) 。
(2)如果mask(i) 为0(因为mask不为空,所以有值,所以当相应的mask(i)=0时),那么不管src(i)是什么,dst(i)都设置为0.
举例说明,这里不举太复杂的就来一个一维的就够啦。

这里写图片描述

上表很明显就是按位与

//如果传递给src的数组是图像类型的,那么将使用ROI或者COI。src数组和dst数组必须具有相同的数据类型、一致的数组维数、一样的大小。该函数也可以用于拷贝稀疏矩阵(但是此种情况下,mask不起作用)。好吧,到这里了终于写完了。你现在是不是明白为什么要起mask这个名字了吧,掩码就是:不为0的时候就可一操作(具体是什么操作就看具体的函数了)、为0就掩盖住了无法操作。
补充一点 :mask = NULL 意思就是没有模板、不使用掩码操作,函数该干啥就干啥。

15.3.2mask!=NULL时的应用——提取不规则区域的实现

由上可知,只要满足以下条件:
(1)只要mask是不规则的图像(灰度图像)
(2)mask的大小 == dst图像大小 == src图像大小(关键,否则运行出错)
(3)在mask图像中想要提取的地方设置为全白,不想包括的地方全黑,这样效果更佳。

程序实例

#include "cv.h"#include "cxcore.h"#include "highgui.h"int main(int argc, char* argv[]){    IplImage *pImg=cvLoadImage("1.jpg");    IplImage *mask=cvLoadImage("c.jpg");    IplImage *dstImg=cvCreateImage(cvGetSize(pImg),8,3);    cvSetZero(dstImg);    cvCopy(pImg,dstImg,mask);    cvNamedWindow("srcShow",1);    cvNamedWindow("dstShow",1);    cvNamedWindow("maskShow",1);    cvShowImage("srcShow",pImg);    cvShowImage("dstShow",dstImg);    cvShowImage("maskShow",mask);    cvWaitKey(0);    cvReleaseImage(&pImg);    cvReleaseImage(&mask);    cvReleaseImage(&dstImg);    cvDestroyWindow("srcShow");    cvDestroyWindow("dstShow");    cvDestroyWindow("maskShow");    return 0;}

其中用到的两幅图片是:
这里写图片描述
1.jpg

这里写图片描述
c.jpg

mask图片相当于一个滤镜的作用,将mask图片盖在原图片上,然后原图片的内容在mask图片的!=0部分(非黑色部分)才会显示出来,mask图片的黑色部分就会遮挡住原图片的内容。
此外,最终显示的是被提取出来的mask图片的非黑色部分。

15.4cvSetZero()

cvSetZero(图片名——IplImage类型的数据);
程序中cvSetZero(dstImg);//相当于初始化图片,值都为0。
0——黑色,255——白色

15.5 cvcopy()

cvcopy : 拷贝一个数组给另一个数组
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
src
输入数组。
dst
输出数组。
mask
操作掩码是8比特单通道的数组,它指定了输出数组中被改变的元素。
函数cvCopy从输入数组中复制选定的成分到输出数组。
所以程序中,cvCopy(pImg,dstImg,mask);
就是指将pImg经过mask之后的结果(非黑色部分)覆盖到dstImg中,得到最终结果。

15.6 cvSet()和cvSetZero()

其结构
void cvSetvalue CvArr* arr,//目标矩阵 CvScalar value,//设置值const,CvArr* mask = NULL//图像开关);
作用:为数组的每个元素设置数值。
这些函数能将数组的所有通道的所有值设置为指定的参数value。该cvSet ( )函数接受一个可选的参数:如果提供参数,函数那么只有那些与参数mask中非0值对应的像素将被设置为指定的值。
cvSetZero()仅仅是cvSet(0.0)别名。

0 0