基于OpenCV 图像分割

一、概述

       从图像中将目标或部分目标分割出来,是我们在进行图像处理的操作,也是有意义的事情。在很多情况下,我们也希望将感兴趣的目标区域分割出来,比如将一个人的脸或手分割出来。具体有下面提到的几种方法。

1、背景减除

        背景减除是在背景模型建立后,将背景模型和当前的图像进行比较,然后减去这些已知的背景信息,则剩下的目标物大致就是所求的前景目标。背景减除法的缺点是假设所有像素点是独立的,这种更完整的空间和时间模型需要更多的内存、收集数据样本更多的以及更多的计算资源。

2、帧差法

       帧差法就是用一帧减去另一帧(也可能是后几帧),然后将足够大的差别标为前景。这种方法是最有效的捕捉运动目标的边缘。可以使用cvAbsDiff(frameTime1, frameTime2, frameForeground)、cvThreshold(frameForeground, frameForeground, 15, 255, CV_THRESH_BINARY)等函数实现。

3、平均背景法

       平均背景法的基本思想是计算每一个像素的平均值和标准差(或相似的,但计算速度更快的平均差值)作为它的背景模型。平均背景法使用四个OpenCV函数:累积图像cvAcc( )、计算一定时间内的每帧图像之差cvAbsDiff( )、将图像分割成前景区域和背景区域cvInRange( )、将不同的彩色通道图像中合成为一个掩码图像cvOr( )

4、codebook背景模型

      codebook由一些boxes组成,这些boxes包含很长时间不变的像素值。如果当前值和历时值相差比较大,就会产生一个新的box来覆盖它,同样慢慢地接近新的值。这种codebook方法能够解决像素激烈变化的问题(例如,被风吹的树的像素,它可能在很多树叶的颜色和数之间的蓝天颜色之间交替出现)。

     我们为每一个像素设置一个码元code_elements,需要有与训练的图像像素数目长度一样的一组码本。对每一个不同的像素,调用函数update_codebook( )以捕捉背景中相关的变化图像。训练可以自始至终定期更新,同时函数clear_stale_entries( )用于训练有移动的前景目标的背景。使用codebook背景分割技术,通常可以有以下步骤:

(1)、使用函数update_codebook( )在几秒钟或几分钟时间内训练一个基本的背景模型。

(2)、调用函数clear_stale_entries( )清除stale索引。

(3)、调整阈值minMod和maxMod对已知前景达到最好的分割。

(4)、保持一个更高级别的场景模型。

(5)、通过函数background_diff( )使用训练好的模型将前景从背景中分割出来。

(6)、定期更新学习的背景像素。

(7)、在一个频率较慢的情况下,用函数clear_stale_entries( )定期清理stale的codebook索引。

5、分水岭算法

     分水岭算法在分割图像是比较有效果的一种。该算法可以将图像中的边缘转化成“山脉”,将平均区域转化为“山谷”,这样有助于分割目标。分水岭算法首先计算灰度图像的梯度,这对山谷或没有纹理的盆地的形式有效,对有山头或图像中有主导的山脉的形成有效。然后开始从用户指定点开始持续灌注盆地直到这些区域连在一起。

 

二、相关函数

1、线采用函数

int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, CvLineIterator* line_iterator,

                                  int connectivity=8, int left_to_right=0 );

img

       用以获取直线的图像。 pt1 线段的第一个端点。 pt2 线段的第二个端点。

line_iterator

      指向直线迭代状态结构体的指针。

connectivity

       直线的邻接方式,4邻接或者8邻接。

left_to_right

       标志值,指出扫描直线是从pt1和pt2外面最左边的点扫描到最右边的点(left_to_right≠0),还是按照指定的顺序,从pt1到pt2(left_to_right=0)。

       函数cvInitLineIterator初始化直线迭代器并返回两个端点间点的数目。两个端点都必须在图像内部。在迭代器初始化以后,所有的在连接两个终点的栅栏线上的点,可以通过访问CV_NEXT_LINE_POINT点的方式获得。在线上的这些点使用4-邻接或者8-邻接的Bresenham算法计算得到。

 

2、计算两个数组差的绝对值

void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );
src1
     第一个原数组
src2
     第二个原数组
dst
     输出数组
     函数 cvAbsDiff 计算两个数组差的绝对值 dst(I)c = abs(src1(I)c - src2(I)c).所有数组必须有相同的数据类型相同的大小(或ROI大小)

 

3、对数组元素进行固定阈值操作

void cvThreshold( const CvArr* src, CvArr* dst, double threshold,
                  double max_value, int threshold_type );

src

     原始数组 (单通道 , 8-bit of 32-bit 浮点数).

dst

     输出数组,必须与 src 的类型一致,或者为 8-bit.

threshold

     阈值

max_value

     使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值.

threshold_type

     阈值类型 (见讨论)

     函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(cvCmpS 也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。本函数支持的对图像取阈值的方法由 threshold_type 确定。

 

4、将帧叠加到累积器(accumulator)中

void cvAcc( const CvArr* image, CvArr* sum, const CvArr* mask=NULL );
image
     输入图像, 1- 或 3-通道, 8-比特或32-比特浮点数. (多通道的每一个通道都单独处理).
sum
    同一个输入图像通道的累积,32-比特或64-比特浮点数数组.
mask
    可选的运算 mask. 
   函数 cvAcc 将整个图像 image 或某个选择区域叠加到 sum 中: sum(x,y)=sum(x,y)+image(x,y) if mask(x,y)!=0

 

5、检查数组元素是否在两个数组之间

void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );
src
    第一个原数组
lower
    包括进的下边界数组
upper
    不包括进的上边界线数组
dst
    输出数组必须是 8u 或 8s 类型.
函数 cvInRange 对输入的数组作范围检查,

对于单通道数组:
    dst(I)=lower(I)0 <= src(I)0 < upper(I)0
对二通道数组:
    dst(I)=lower(I)0 <= src(I)0 < upper(I)0 && lower(I)1 <= src(I)1 < upper(I)1
以此类推
    如果 src(I) 在范围内dst(I)被设置为 0xff (每一位都是 '1')否则置0 。 除了输出数组所有数组必须是相同的类型相同的大小(或ROI大小)。

 

6、计算两个数组每个元素的按位或

void cvOr( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
    第一个原数组
src2
    第二个原数组
dst
    输出数组.
mask
   操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改。

函数 cvOr 计算两个数组每个元素的按位或: dst(I)=src1(I)|src2(I)。对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。

 

7、叠加输入图像的平方到累积器中

void cvSquareAcc( const CvArr* image, CvArr* sqsum, const CvArr* mask=NULL );
image
    输入图像, 1- 或 3-通道, 8-比特或32-比特浮点数 (多通道的每一个通道都单独处理)
sqsum
   同一个输入图像通道的累积,32-比特或64-比特浮点数数组.
mask
   可选的运算 mask.
函数 cvSquareAcc 叠加输入图像 image 或某个选择区域的二次方,到累积器 sqsum 中 sqsum(x,y)=sqsum(x,y)+image(x,y)2 if mask(x,y)!=0

 

8、将两幅输入图像的乘积叠加到累积器中

void cvMultiplyAcc( const CvArr* image1, const CvArr* image2, CvArr* acc, const CvArr* mask=NULL );
image1
   第一个输入图像, 1- or 3-通道, 8-比特 or 32-比特 浮点数 (多通道的每一个通道都单独处理)
image2
   第二个输入图像, 与第一个图像的格式一样
acc
   同一个输入图像通道的累积,32-比特或64-比特浮点数数组.
mask
   可选的运算 mask. 
函数 cvMultiplyAcc 叠加两个输入图像的乘积到累积器 acc: acc(x,y)=acc(x,y) + image1(x,y)?image2(x,y) if mask(x,y)!=0

 


 




 

 

 


 

 

 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值