关闭

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

标签: opencv
118人阅读 评论(0) 收藏 举报
分类:

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

#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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:14115次
    • 积分:608
    • 等级:
    • 排名:千里之外
    • 原创:49篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    文章分类