基于opencv颜色阈值分割

2016-08-18 阅读答案 阅读:

基于opencv颜色阈值分割(一)
基于OpenCV的图像阈值分割研究与实现[精品资料]

基于OpenCV的图像阈值分割研究与实现-精品资料

本文档格式为WORD,感谢你的阅读

摘 要: 图像的阈值化在图像分割中有着至关重要的作用。在OpenCV 算法环境下,运用固定阈值化和自适应阈值化算法,分别对同一幅图调用OpenCV 中相应的函数进行处理;同时针对图像中的噪声,结合高斯模糊算法对图像噪声的滤除作用,将高斯模糊和阈值化算法结合起来,分析研究图像分割算法。结果表明自适应阈值化算法可以更有效地进行图像分割。

关键字: OpenCV; 自适应阈值; 图像分割; 固定阈值

TN919?34; TP32 A 1004?373X(2013)24?0073?04 Research and implementation of image threshold segmentation based on OpenCV

LEI Jian?feng, WANG Wei

(Capital Medical University, Beijing 100069, China)

Abstract:The image threshold plays a very important role in image segmentation. In the OpenCV algorithm environment, the fixed threshold algorithm and adaptive threshold algorithm are emploied

respectively to process the same image by calling the corresponding function in OpenCV. The noise in the image is eliminated in combination with the filtering function of Gauss fuzzy algorithm. The image

segmentation algorithm was analyzed by means of Gauss

fuzzy and thresholding algorithm. The results show that the adaptive threshold algorithm can perform image segmentation more efficiently.

Keyword: OpenCV; adaptive threshold; image segmentation; fixed threshold

1 OpenCV简介

OpenCV是一种开源的软件,采用基于C/C++语言编写,OpenCV可以在多种操作系统上运行同时为其他软件提供了多种接口。在数据类型上OpenCV提供了多种基本数据类型。虽然这些数据类型在C语言中不是基本类型,但结构都很简单,可将它们作为原子类型。OpenCV 主体分为5个模块,其中4个模块如图1所示。

图1 OpenCV基本结构图

OpenCV的目标是为计算机视觉提供基本工具,在处理计算机视觉中一些很复杂的问题时,可以利用OpenCV提供的高层函数有效地解决这些问题。OpenCV有一个强大的函数库,它可以提供基本函数为大多数计算机视觉问题创建一个完整解决方案。

2 图像分割

图像分割[1]是图像分析中很重要的基础环节,只有准确地将对象从图像中提取出来,才能进一步对该对象做定量的描绘。图像分割又是比较困难的环节,因为在许多情况下,对象与背景之间很难区分。所以图像分割算法已经成为图像处理

[2]和分析领域中研究的热点,并且到目前为止没有一种通用的分割算法对各种图像均能得到满意的分割结果。图像分割的准则实质是将一幅图像分成几幅子图像,并且满足3个条件:

(1)图像中的每一个像素必须被归入某一子图像,并只能属于一个子图像;

(2)属于同一子图像的像素在某种性质上是相近的;

(3)属于不同子图像的像素在该性质上相差很大。所谓性质指的是如灰度、灰度梯度、纹理以及空间位置等。因此,图像分割的过程也就是按性质对像素进行分类和识别。 图像分割[3]方法一般有2类:

(1)基于边界分割方法,这种方法通过子图像之间一般都有明显的边界。假设图像中只有2个子图像,子图像不存在多个互不连通的区域;

(2)基于阈值方法,这种方法首先根据像素的某个特征确定分割阈值,然后将像素的这个特征值与此分割阈值相比较,并以此决定将该像素归入哪一类子图像。通常将像素的灰度作为特征来选择阈值。

2.1 VC6.0下OpenCV的安装及环境搭配

(1)下载OpenCV安装程序(1.0版本)。假如要将OpenCV安装到C:\Program Files\OpenCV。在安装时选择“将\OpenCV\bin加入系统变量”。或安装完成后手动添加环境变量“C:\Program Files\OpenCV\bin”。

(2)启动VC++ 6.0,菜单

Tools?>Options?>Directories:先设置lib路径,选择Library files,在下方填入路径: C:\Program Files\OpenCV\lib然后选择include files,在下方填入路径: C:\Program Files\OpenCV\cxcore\include C:\Program Files\OpenCV\cv\include

C:\Program Files\OpenCV\cvaux\include C:\Program Files\OpenCV\ml\include

C:\Program Files\OpenCV\otherlibs\highgui C:\Program Files\OpenCV\otherlibs\cvcam\include

(3)每创建一个将要使用OpenCV的VC Project,都需要给它指定需要的lib。菜单:Project?>Settings,然后将Setting for选为All Configurations,然后选择右边的link标签,在Object/library modules附加上:cxcore.lib

cv.lib ml.lib cvaux.lib highgui.lib cvcam.lib如果不需要这么多lib,你可以只添加你需要的lib。

2.2 利用OpenCV进行图像阈值分割

阈值分割是传统的图像分割方法,因其实现简单,性能较稳定而成为图像分割中最基本和应用最广泛的分割技术

[4]。它适用于目标和背景有不同灰度级范围的图像,而且总可以得到封闭且连通区域的边界。

2.2.1 阈值分割的概念

阈值分割法是一种基于区域的图像分割技术,其基本原理是:通过设定不同的特征阈值,把图像象素点分为若干类

[5]。通常将像素的灰度作为特征来选择阈值。首先设原始图像为f(x,y),然后按照一定的准则f(x,y)中找到特征值T,将图像分割为2个部分,分割后的图像为: 若取b0=0(黑),b1=1(白),即为图像二值化。该方法的特点是可以减少数据量,而且简化了分析和处理步骤,因此该方法是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。图像阈值化的目的是要按照灰度级,对像素集合进行一个划分,使每个子集形成一个与现实景物相对应的区域,各个区域内部具有一致的属性,而相邻区域具有不同的属性。这样的划分可以通过从灰度级出发选取一个或多个阈值来实现。

2.2.2 OpenCV实现阈值分割方法

OpenCV实现阈值分割方法[6]:

(1)固定阈值分割,在OpenCV中实现固定阈值分割的函数是cvThreshold(),函数 cvThreshold()对单通道数组应用固定阈值操作。其基本的思想是,给定一个数组和一个阈值,然后根据数组中的每个元素的是低于还是高于阈值而进行一些处理。

(2)自适应阈值分割,在OpenCV中实现自适应阈值分割的函数AdaptiveThreshold(),此函数有2种不同的自适应阈值方法。

2.2.3 基于MFC的OpenCV阈值分割的实现【基于opencv颜色阈值分割】

OpenCV 库是使用“IplImage”结构体来创建和处理图像,在其库函数中,最重要的结构体就是IplImage 结构,使用这种格式的特点是:可以比DIB 格式表示更多的图像性质,而且可以更方便地存取图像中的像素值[7]。定义该结构体变量时,需要用到函数cvCreateImage,定义方法如下: IplImage *src=cvCreateImage(cvSize(800,600),IPL_DEPTH_16U,3);

在VC6.0 中新建MFC AppWizard(exe),添加支持OpenCV 的库文件,如cxcore.lib cv.libml.lib cvaux.lib highgui.lib cvcam.lib 等,使得VC能够调用OpenCV 的库函数。

(1)固定阈值算法

OpenCV 中使用固定阈值对图像进行二值化的函数是cvThreshold(),函数具体定义为:

Double cvThreshold(

CvArr* src,

CvArr* dst,

double threshold,

double max_value,

int threshold_type);

该函数的特点是只能处理8位或浮点灰度图像。目标图像必须与源图像的类型一致。每个阈值类型threshold_type对应于一个特定的比较操作如表1所示,该比较操作在源图像第i个像素(srci)和阈值(T)之间进行。根据源图像的像素和阈值之间的关系,目标图像的像素dsti 会被设置为0, srci 或者max_value。当threshold_type 被设置为

CV_THRESH_BINARY 时,如果源图像第i 个像素(srci)大于阈值T,则目标像素dsti 被设置为最大值max_value。否则目标像素dsti 被设置为0[8]。

表1 cvThreshold()中阈值类型选项和对应的操作

基于opencv颜色阈值分割(二)
opencv实现c++的otsu自适应阈值分割的算法描述

otsu算法选择使类间方差最大的灰度值为阈值,具有很好的效果

算法具体描述见otsu论文,或冈萨雷斯著名的数字图像处理那本书【基于opencv颜色阈值分割】

这里给出程序流程:

1、计算直方图并归一化histogram

2、计算图像灰度均值avgValue.

3、计算直方图的零阶w[i]和一级矩u[i]

4、计算并找到最大的类间方差(between-class variance)

variance[i]=(avgValue*w[i]-u[i])*(avgValue*w[i]-u[i])/(w[i]*(1-w[i]))

对应此最大方差的灰度值即为要找的阈值

5、用找到的阈值二值化图像

我在代码中做了一些优化,所以算法描述的某些地方跟程序并不一致

otsu代码,先找阈值,继而二值化

// implementation of otsu algorithm

// author: onezeros(@yahoo.cn)

// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB

void cvThresholdOtsu(IplImage* src, IplImage* dst)

{

int height=src->height;

int width=src->width;

//histogram

float histogram[256]= {0};

for(int i=0; i<height; i++)

{

unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i; for(int j=0; j<width; j++)

{

histogram[*p++]++;

}【基于opencv颜色阈值分割】

}

//normalize histogram

int size=height*width;

for(int i=0; i<256; i++)

{

histogram[i]=histogram[i]/size;

}

//average pixel value

float avgValue=0;

for(int i=0; i<256; i++)

{

avgValue+=i*histogram[i];

}

int threshold;

float maxVariance=0;

float w=0,u=0;

for(int i=0; i<256; i++)

{

w+=histogram[i];

u+=i*histogram[i];

float t=avgValue*w-u;

float variance=t*t/(w*(1-w));

if(variance>maxVariance)

{

maxVariance=variance;

threshold=i;

}

}

cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);

}

更多情况下我们并不需要对每一帧都是用otsu寻找阈值,于是可以先找到阈值,然后用找到的阈值处理后面的图像。下面这个函数重载了上面的,返回值就是阈值。只做了一点改变

// implementation of otsu algorithm

// author: onezeros(@yahoo.cn)

// reference: Rafael C. Gonzalez. Digital Image Processing Using MATLAB

int cvThresholdOtsu(IplImage* src)

{

int height=src->height;

int width=src->width;

//histogram

float histogram[256]= {0};

for(int i=0; i<height; i++)

{

unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i; for(int j=0; j<width; j++)

{

histogram[*p++]++;

}

}

//normalize histogram

int size=height*width;

for(int i=0; i<256; i++)

{

histogram[i]=histogram[i]/size;

}

//average pixel value

float avgValue=0;

for(int i=0; i<256; i++)

{

avgValue+=i*histogram[i];

}

int threshold;

float maxVariance=0;

float w=0,u=0;

for(int i=0; i<256; i++)

{

w+=histogram[i];

u+=i*histogram[i];

float t=avgValue*w-u;

float variance=t*t/(w*(1-w));

if(variance>maxVariance)

{

maxVariance=variance;

threshold=i;

}

}

return threshold;

}

我在手的自动检测中使用这个方法,效果很好。

下面是使用上述两个函数的简单的主程序,可以试运行一下,如果处理视频,要保证第一帧时,手要在图像中。

#include <cv.h>

#include <cxcore.h>

#include <highgui.h>

#pragma comment(lib,"cv210d.lib")

#pragma comment(lib,"cxcore210d.lib")

#pragma comment(lib,"highgui210d.lib")

#include <iostream>

using namespace std;

int main(int argc, char** argv)

{

#ifdef VIDEO //video process

CvCapture* capture=cvCreateCameraCapture(-1);

if (!capture)

{

cout<<"failed to open camera"<<endl;

exit(0);

}

int threshold=-1;

IplImage* img;

while (img=cvQueryFrame(capture))

{

cvShowImage("video",img);

cvCvtColor(img,img,CV_RGB2YCrCb);

IplImage* imgCb=cvCreateImage(cvGetSize(img),8,1);

cvSplit(img,NULL,NULL,imgCb,NULL);

if (threshold<0)

{

threshold=cvThresholdOtsu(imgCb);

}

//cvThresholdOtsu(imgCb,imgCb);

cvThreshold(imgCb,imgCb,threshold,255,CV_THRESH_BINARY); cvErode(imgCb,imgCb);

cvDilate(imgCb,imgCb);

cvShowImage("object",imgCb);

cvReleaseImage(&imgCb);

if (cvWaitKey(3)==27) //esc

{

break;

}

}

cvReleaseCapture(&capture);

#else //single image process

const char* filename=(argc>=2?argv[1]:"cr.jpg");

IplImage* img=cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE);

【基于opencv颜色阈值分割】

cvThresholdOtsu(img,img);

cvShowImage( "src", img );

char buf[256];

sprintf_s(buf,256,"%s.otsu

基于opencv颜色阈值分割

http://m.zhuodaoren.com/yuwen338790/

推荐访问:opencv阈值化

阅读答案推荐文章

推荐内容

上一篇:蒲松龄,《赠妓》 下一篇:花家喜事1全文阅读