cvPyrSegmentation
PyrSegmentation
用金字塔实现图像分割
void cvPyrSegmentation( IplImage* src, IplImage* dst,
CvMemStorage* storage, CvSeq** comp,
int level, double threshold1, double threshold2 );
src
输入图像.
dst
输出图像.
storage
Storage: 存储连通部件的序列结果
comp
分割部件的输出序列指针 components.
level
建立金字塔的最大层数
threshold1
建立连接的错误阈值
threshold2
分割簇的错误阈值
函数 cvPyrSegmentation 实现了金字塔方法的图像分割。金字塔建立到 level 指定的最大层数。如果 p(c(a),c(b))<threshold1,则在层 i 的象素点 a 和它的相邻层的父亲象素 b 之间的连接被建立起来,
定义好连接部件后,它们被加入到某些簇中。如果p(c(A),c(B))<threshold2,则任何两个分割 A 和 B 属于同一簇。
如果输入图像只有一个通道,那么
p(c1,c2)=|c1-c2|.
如果输入图像有单个通道(红、绿、兰),那幺
p(c1,c2)=0,3·(c1r-c2r)+0,59·(c1g-c2g)+0,11·(c1b-c2b) .
每一个簇可以有多个连接部件。图像 src 和 dst 应该是 8-比特、单通道 或 3-通道图像,且大小一样
cvGetSeqElem
openCV里面的一个函数
作用:直接访问序列中的元素
格式:char * cvGetSeqElem(seq,index)
用法:
1. 首先返回的是char类型的指针,当然也可以利用强制类型转换,转换为序列中实际存储的数据类型
例如:for(int i = 0; i<seq ->total;++i)
{
CvPoint *p = (CvPoint *)cvGetSeqElem(seq,i);
}
2. seq是需要检测的序列,而index顾名思义是元素在序列中的索引,即第几个元素
CvMemStorage
CvMemStorage
Growing memory storage
typedef struct CvMemStorage
{
struct CvMemBlock* bottom;/* first allocated block */
struct CvMemBlock* top; /* the current memory block - top of the stack */
struct CvMemStorage* parent; /* borrows new blocks from */
int block_size; /* block size */
int free_space; /* free space in the top block (in bytes) */
} CvMemStorage;
内存存储器是一个可用来存储诸如序列,轮廓,图形,子划分等动态增长数据结构的底层结构。它是由一系列以同等大小的内存块构成,呈列表型 ---bottom 域指的是列首,top 域指的是当前指向的块但未必是列尾.在bottom和top之间所有的块(包括bottom, 不包括top)被完全占据了空间;在 top和列尾之间所有的块(包括块尾,不包括top)则是空的;而top块本身则被占据了部分空间 -- free_space 指的是top块剩馀的空字节数。
新分配的内存缓冲区(或显式的通过 cvMemStorageAlloc 函数分配,或隐式的通过 cvSeqPush, cvGraphAddEdge等高级函数分配)总是起始于当前块(即top块)的剩馀那部分,如果剩馀那部分能满足要求(够分配的大小)。分配后,free_space 就减少了新分配的那部分内存大小,外加一些用来保存适当列型的附加大小。当top块的剩馀空间无法满足被分配的块(缓冲区)大小时,top块的下一个存储块被置为当前块(新的top块) -- free_space 被置为先前分配的整个块的大小。
如果已经不存在空的存储块(即:top块已是列尾),则必须再分配一个新的块(或从parent那继承,见 cvCreateChildMemStorage)并将该块加到列尾上去。于是,存储器(memory storage)就如同栈(Stack)那样, bottom指向栈底,(top, free_space)对指向栈顶。栈顶可通过 cvSaveMemStoragePos保存,通过 cvRestoreMemStoragePos 恢复指向, 通过 cvClearStorage 重置。
//源代码:
// 金字塔分割(Trackbar).cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include"cv.h"
#include"highgui.h"
char wndname[] = "Show";
char tbarname0[] = "Level";
char tbarname1[] = "Threshold1";
char tbarname2[] = "Threshold2";
int edge_thresh0 = 1;
int edge_thresh1 = 50;
IplImage* resize=0;
IplImage* dst=0;
void on_trackbar(int edge_thresh0, int edge_thresh1)
{
cvNamedWindow( "resize", 1 );
// Show the image in the named window
cvShowImage( "resize", resize );
//cvWaitKey(0);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* comp = NULL;
cvPyrSegmentation(resize,dst,storage,&comp, edge_thresh0, edge_thresh1, edge_thresh1*3);
for (int i=0;i<comp->total;++i)
{
CvConnectedComp* cc=(CvConnectedComp*)cvGetSeqElem(comp,i);//链接图像
}
cvReleaseMemStorage(&storage);
// Show the image in the named window
cvShowImage( wndname, dst );
}
int main()
{
IplImage* src=cvLoadImage("E:/photo/Lena.jpg",1);
//图像大小必须能被2^level整除
resize=cvCreateImage(cvSize(512,512),8,3);
dst=cvCreateImage(cvSize(512,512),8,3);
cvResize(src,resize);
cvNamedWindow( wndname, 1 );
while (1)
{
cvCreateTrackbar(tbarname0, wndname, &edge_thresh0, 8 );
cvCreateTrackbar(tbarname1, wndname, &edge_thresh1, 100);
on_trackbar(edge_thresh0,edge_thresh1);
// Wait for a key stroke; the same function arranges events processing
// Press any key to exit.
// Clean up and don’t be piggies
cvWaitKey(30);
}
cvReleaseImage( &src );
cvReleaseImage( &dst );
cvDestroyWindow(wndname);
return 0;
}