金字塔图像分割原理解析与示例[opencv]

图像分割指的是将数字图像细分为多个图像子区域的过程,在OpenCv中实现了三种跟图像分割相关的算法,它们分别是:金字塔分割算法,分水岭分割算法以及均值漂移分割算法。它们的使用过程都很简单,刚开始学习opencv,先记录一下我对金字塔分割原理的理解吧。

金字塔分割算法     

金字塔分割算法由cvPrySegmentation所实现,该函数的使用还是比较简单;需要注意的是图像的尺寸以及金字塔的层数,图像的宽度和高度必须能被2整除,能够被2整除的次数决定了金字塔的最大层数。下面的代码演示了如何校验金字塔层数:

/// 
/// 当改变金字塔分割的参数“金字塔层数”时,对参数进行校验
/// 
private void txtPSLevel_TextChanged(object sender, EventArgs e){
	int level = int.Parse(txtPSLevel.Text);
		if (level < 1 || imageSource.Width % (int)(Math.Pow(2, level - 1)) != 0 || imageSource.Height % (int)(Math.Pow(2, level - 1)) != 0){			MessageBox.Show(this, "输入的金字塔层数不符合要求,计算结果可能会无效。", "金字塔层数错误!")
}

opencv中有分装好的函数库,

void pyrMeanShiftFiltering( 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))

如果p(c(A),c(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-通道图像,且大小一样    Threshold1,Threshold2的解读:金字塔分割先通过p(c(a),c(b))

这是一个测试例子:

#include 
#include 
#include 
#include 

using namespace cv;
using namespace std;
Mat src, dst;
int spatialRad , colorRad , maxPryLevel; //空间,颜色,金字塔层数

void meanshift_seg()
{
	调用meanshift图像金字塔进行分割
	pyrMeanShiftFiltering(src, dst, spatialRad, colorRad, maxPryLevel);  
	RNG rng = theRNG();
	Mat mask(dst.rows + 2, dst.cols + 2, CV_8UC1, Scalar::all(0));
	for (int i = 0; i(i + 1, j + 1) == 0)
	{
		Scalar newcolor(rng(256), rng(256), rng(256));
		floodFill(dst, mask, Point(j, i), newcolor, 0, Scalar::all(1), Scalar::all(1));
	}
	imshow("结果图像", dst);
}

void meanshift_seg_s(int i, void *)   //控制滑动块
{
	spatialRad = i;
	meanshift_seg();
}

void meanshift_seg_c(int i, void *)
{
	colorRad = i;
	meanshift_seg();
}

void meanshift_seg_m(int i, void *)
{
	maxPryLevel = i;
	meanshift_seg();
}

int main(int argc, uchar* argv[])
{

	namedWindow("载入原图像", WINDOW_AUTOSIZE);
	namedWindow("结果图像", WINDOW_AUTOSIZE);

	src = imread("../pict1.jpg");
	CV_Assert(!src.empty());

	spatialRad = 10;
	colorRad = 10;
	maxPryLevel = 1;
	createTrackbar("空间度", "结果图像", &spatialRad, 80, meanshift_seg_s);
	createTrackbar("色度", "结果图像", &colorRad, 255, meanshift_seg_c);
	createTrackbar("金字塔层级", "结果图像", &maxPryLevel, 5, meanshift_seg_m);
	imshow("载入原图像", src);
	imshow("结果图像", src);
	waitKey();
	return 0;
}
结果图:



可以调节,当金字塔层级越高时候,切割效果越明显。好了,今天就不写了,我去上课了,后面继续。。。

你可能感兴趣的:(金字塔图像分割原理解析与示例[opencv])