opencv学习笔记(十七)利用cvPyrSegmentation()做图像分割

来源:互联网 发布:淘宝app如何收藏店铺 编辑:程序博客网 时间:2024/06/05 19:30

图像分割的意义:

在一幅图像中,人们常常只对其中的部分目标感兴趣,这些目标通常占据一定的区域,并且在某些特性(如灰度、轮廓、颜色和纹理等)上和临近的图像有差别。这些特性差别可能非常明显,也可能很细微,以至肉眼察觉不出来。随着计算机图像处理技术的发展,使得人们可以通过计算机来获取和处理图像信息。图像识别的基础是图像分割,其作用是把反映物体真实情况的、占据不同区域的、具有不同特性的目标区分开来,并形成数字特征。图像分割是图像识别和图像理解的基本前提步骤,图像分割质量的好坏直接影响后续图像处理的效果,甚至决定其成败,因此,图像分割的作用是至关重要的。

cvPyrSegmentation()

有许多操作广泛使用高斯金字塔和拉普拉斯金字塔,但一个特别重要的应用就是利用金字塔实现图像分割。图像分割需要先建立一个图像金字塔,然后在Gi的像素和Gi+1的像素直接依照对应关系,建立起“父—子”关系。通过这种方式,快速初始分割可以先在金字塔高层的低分辨率图像上完成,然后逐层对分割加以优化。

OpenCV的函数cvPyrSegmentation()实现了该算法。
void cvPyrSegmentation(
IplImage* src,
IplImage* dst,
CvMemStorage* storage,
CvSeq** comp,
int level,
double threshold1,
double threshold2
);
参数:
src
输入图像
dst
输出图像
storage: 存储连通部件的序列结果,这里面应该存的是分割的坐标,即每一个分割都是有哪些坐标构成的
comp 分割部件的输出序列指针components就相当于指向一堆点集(构成分割域的点集)的指针
level 建立金字塔的最大层数,金子塔的层数
threshold1 建立连接的错误阈值,当一些值小于这个值时就把这些值相连结
threshold2 分割簇的错误阈值,当一些值小于这个值时就把这些值当做是一个区域
像以前介绍的一样,src 和std分别是源图像和目标图像,它们都必须是8位的,且具有相同的图像大小和通道的数量(1或3)。
关于src和dst ,需要特别注意一点:由于图像金字塔各层的长和宽都必须是整数,所以必须要求起始图像的长和宽都能够被2整除,并且能够被2整除的次数不少于金字塔总的层数。例如,对于4层金字塔的高度或宽度为80(2×2×2×5)是满足要求的,而为90时(2×3×3×5)就不符合要求了。
指针storage用来指向OpenCV的存储区。

程序实例

#include <highgui.h>  #include<cv.h>   #include <opencv2/legacy/legacy.hpp>   int t;  int level=1;    int threshold1=10;  int threshold2=10;    IplImage *img_in;  IplImage *img_out;  IplImage *img2;  CvMemStorage *stoage ;  CvSeq* comp=NULL;   using namespace std;  void on_trackbar_1(int level_pos)  {      level=level_pos;  cvPyrSegmentation(img_in,img_out,stoage,&comp,level,threshold1,threshold2);       cvNamedWindow("img_out",CV_WINDOW_AUTOSIZE);      cvShowImage("img_out",img_out);  }  void on_trackbar_2(int threshold1_pos)  {      threshold1=threshold1_pos;        cvPyrSegmentation(img_in,img_out,stoage,&comp,level,threshold1,threshold2);       cvNamedWindow("img_out",CV_WINDOW_AUTOSIZE);      cvShowImage("img_out",img_out);  }    void on_trackbar_3(int threshold2_pos)  {      threshold2=threshold2_pos;  cvPyrSegmentation(img_in,img_out,stoage,&comp,level,threshold1,threshold2);       cvNamedWindow("img_out",CV_WINDOW_AUTOSIZE);      cvShowImage("img_out",img_out);  }  int main()  {      stoage = cvCreateMemStorage();      img_in = cvLoadImage("a.jpg");      img_out = cvCreateImage(cvSize(img_in->width,img_in->height),IPL_DEPTH_8U,3);            img2 = cvCreateImage(cvSize(500,500),IPL_DEPTH_8U,3);        cvNamedWindow("img_in",CV_WINDOW_AUTOSIZE);      cvShowImage("img_in",img_in);      cvNamedWindow("img2",CV_WINDOW_AUTOSIZE);       cvCreateTrackbar("Level","img2",&t,4,on_trackbar_1);      cvCreateTrackbar("threshold1","img2",&t,200,on_trackbar_2);         cvCreateTrackbar("threshold2","img2",&t,100,on_trackbar_3);         cvWaitKey(0);      cvDestroyAllWindows();      cvReleaseImage(&img_in);        return 0;   }  

说明

opencv2/opencv.hpp这个头文件必须加入。
此外,关于滚动条的函数在视频播放控制那篇博客里面有。

cvCreateMemStorage()

指针storage用来指向OpenCV的存储区,以下命令可以分配存储区域:
CvMemStorage* storage=cvCreateMemStorage( );

0 0
原创粉丝点击