图像金字塔
图像金字塔是一个图像的集合,集合中所有的图像源于同一个原始图像,而且是通过对原始图像连续采样获得,直到达到某个终止条件才停止采样。
图像金字塔有两种,高斯金字塔和拉普拉斯金字塔
高斯金子塔用来向下采样图像,拉普拉斯金字塔用来从金字塔底层图像中向上采样重建一个图像
PyrDown
图像的下采样
void cvPyrDown( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 );
-
src
- 输入图像. dst
- 输出图像, 宽度和高度应是输入图像的一半 ,传入前必须已经完成初始化 filter
- 卷积滤波器的类型,目前仅支持 CV_GAUSSIAN_5x5
函数 cvPyrDown 使用 Gaussian 金字塔分解对输入图像向下采样。首先它对输入图像用指定滤波器进行卷积,然后通过拒绝偶数的行与列来下采样图像。
PyrUp
图像的上采样
void cvPyrUp( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 );
-
src
- 输入图像. dst
- 输出图像, 宽度和高度应是输入图像的2倍 filter
- 卷积滤波器的类型,目前仅支持 CV_GAUSSIAN_5x5
函数 cvPyrUp 使用Gaussian 金字塔分解对输入图像向上采样。首先通过在图像中插入 0 偶数行和偶数列,然后对得到的图像用指定的滤波器进行高斯卷积,其中滤波器乘以4做插值。所以输出图像是输入图像的 4 倍大小。(hunnish: 原理不清楚,尚待探讨)
应用程序:
/*
* 图像金字塔
*/
#include "highgui.h"
#include "cv.h"
void doPyr(IplImage* img)
{
IplImage* pyrd = cvCreateImage(
cvSize(img->width/2, img->height/2),
img->depth,
img->nChannels
);
IplImage* pyru = cvCreateImage(
cvSize(img->width*2, img->height*2),
img->depth,
img->nChannels
);
//图像金字塔
cvPyrDown(img,pyrd,CV_GAUSSIAN_5x5);
cvPyrUp(img,pyru,CV_GAUSSIAN_5x5);
cvNamedWindow("PyrDown");
cvNamedWindow("PyrUp");
cvShowImage("PyrDown",pyrd);
cvShowImage("PyrUp",pyru);
cvReleaseImage(&pyrd);
cvReleaseImage(&pyru);
cvWaitKey(0);
cvDestroyWindow("PyrDown");
cvDestroyWindow("PyrUp");
}
输出结果:
原图
图像分割
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(c¹,c²)=|c¹-c²|.
如果输入图像有单个通道(红、绿、兰),那幺
p(c¹,c²)=0,3·(c¹r-c²r)+0,59·(c¹g-c²g)+0,11·(c¹b-c²b) .
每一个簇可以有多个连接部件。 图像 src 和 dst 应该是 8-比特、单通道 或 3-通道图像,且大小一样
CvConnectedComp
连接部件
typedef struct CvConnectedComp { double area; /* 连通域的面积 */ float value; /* 分割域的灰度缩放值 */ CvRect rect; /* 分割域的 ROI */ } CvConnectedComp;
程序代码:
/*
* 图像分割
*/
#include "highgui.h"
#include "cv.h"
#include<cxcore.h>
#include<opencv2/legacy/legacy.hpp>
#pragma comment(lib,"opencv_legacy249.lib")
void f(IplImage* img, IplImage* dst);
void doSegment(IplImage *img)
{
IplImage* dst = cvCreateImage(
cvGetSize(img),
img->depth,
img->nChannels
);
f(img, dst);
cvNamedWindow("dst");
cvShowImage("dst",dst);
cvReleaseImage(&dst);
cvWaitKey(0);
cvDestroyWindow("dst");
}
void f(IplImage* img, IplImage* dst)
{
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* comp = NULL;
cvPyrSegmentation(img,dst,storage, &comp, 4, 200, 50);
int n_comp = comp->total;
for(int i = 1; i < n_comp; i++)
{
CvConnectedComp* cc = (CvConnectedComp*) cvGetSeqElem(comp,i);
}
cvReleaseMemStorage(&storage);
}
结果: