Visual C++:MeanShift算法
2010/10/22 16:51
说明:
1.Meanshift.h 中包含一个图像类CImage ,这个可能每个人用的图像类都不一样,要根 据你自己的图像类做相应的修改。
2.分割时,是把不同区域的均值做为该区域的全部像素的值。这一点可以在程序中看到。
3.窗宽的选择很重要,请根据实际情况自己选择。
4.为了节约运算时间,算法的迭代过程只进行了一次。
5.该类在VS2005 Visual C++下测试通过。
// Meanshift.h: interface for the CMeanshift class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MEANSHIFT_H__E6E877AA_4E4D_42A7_BE5F_7A021E6311E9__INCLUDED_)
地海传奇#define AFX_MEANSHIFT_H__E6E877AA_4E4D_42A7_BE5F_7A021E6311E9__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Image.h"
class CMeanshift
{
public:
double computeweigth(CImage& ori_img, int i,int j,int x,int y,unsigned char currentvalue);
unsigned char MSsmooth(CImage& ori_img,int x,int y);
CMeanshift();
CMeanshift(int spatial_kwidth,int range_kwidth,char kind);
virtual ~CMeanshift();
BOOL meanshiftsmooth(CImage & ori_img,CImage & out_img);
BOOL initmeanshift(char kind);
BOOL meanshiftg(CImage &image,int nthreshold);//对经过平滑之后的图像进行分割
private:
double* m_pspatial_weigth; 祝你一路顺风吉他谱
double* m_prange_weigth;
char m_ckind; // the type of the kernel function;either 'guass" or "flat"
int m_ispatial_kwidth; // spatial kernal width
int m_irange_kwidth; // range kernal width
};
#endif // !defined(AFX_MEANSHIFT_H__E6E877AA_4E4D_42A7_BE5F_7A021E6311E9__INCLUDED_)
// Meanshift.cpp: implementation of the CMeanshift class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Meanshift.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
加拿大著名景点
CMeanshift::CMeanshift()
{
}
CMeanshift::CMeanshift(int spatial_kwidth,int range_kwidth,char kind)
{
m_ispatial_kwidth = spatial_kwidth;
m_irange_kwidth = range_kwidth;
m_ckind = kind;
}孟铸
CMeanshift::~CMeanshift()
风险的概念{
}博尔特训练
BOOL CMeanshift::meanshiftsmooth(CImage& ori_img,CImage& out_img)
{
int i,j;
int img_width = ori_img.GetWidth();
int img_height = ori_img.GetHeigth();
if(!initmeanshift(m_ckind))
{
return FALSE;
}
if (!out_img.Create(CSize(img_width,img_height),FALSE))
{
return FALSE;
}
for(i = 0; i < img_height; i++)
{
for(j = 0; j < img_width; j++)
{
out_img.m_pR[i*img_width + j] = MSsmooth(ori_img,i,j);
}
}
return TRUE;
}
BOOL CMeanshift::initmeanshift(char kind)
{
int i_tempspatialnumber = 2*m_ispatial_kwidth*m_ispatial_kwidth;
int i_temprangenumber = 5*m_irange_kwidth;
CString strTemp;
m_pspatial_weigth = new double[i_tempspatialnumber];
m_prange_weigth = new double[i_temprangenumber];
if(kind =='G') //guass kernel
{
for(int i = 0; i < i_tempspatialnumber; i++)
{
m_pspatial_weigth[i] = exp(-(double)(i)/m_ispatial_kwidth/m_ispatial_kwidth);
/*
#if _DEBUG
strTemp.Format("%f",m_pspatial_weigth[i]);
AfxMessageBox(strTemp);
#endif*/
}
for(int j = 0; j < i_temprangenumber; j++)
{
m_prange_weigth[j] = exp(-(double)(j*j)/m_irange_kwidth/m_irange_kwidth);
}
#if _DEBUG
AfxMessageBox("initmeanshift g");
#endif
}
if(kind =='F') //flat kernel
{
for(int i = 0; i < i_tempspatialnumber; i++)
{
m_pspatial_weigth[i] = 1 - i/m_ispatial_kwidth/m_ispatial_kwidth;
m_pspatial_weigth[i] = max(m_pspatial_weigth[i],0 );
}
for(int j = 0; j<i_temprangenumber; j++)
{
m_prange_weigth[j] = 1 -j/m_irange_kwidth/m_irange_kwidth;
m_prange_weigth[j] = max(m_prange_weigth[j],0);
}
}鲁迅二十四孝图
return true;
}
/************************************************************
* input :
* ori_img ----orignal image
* m_prange_weigth----range weights
* m_pspatial_weigth----spatial weights
* x, y----- the coordinate of the current point:
* x--height;
* y--width;
*
*************************************************************/
unsigned char CMeanshift::MSsmooth(CImage& ori_img,int x,int y)
{
unsigned char currentvalue;
double temp_value = 0;
double totol_weigh = 0;
double result;
double temp_weigth;
BOOL b_stop = fal;
double temp_img_x = 0;
double temp_img_y = 0;
int i,j;
int height_idx = 0;
int width_jdx = 0;
int k = 1;
int newx,newy;
int img_width = ori_img.GetWidth();
int img_height = ori_img.GetHeigth();
currentvalue = ori_img.m_pR[x*img_width+y];
while(k < 2 ||!b_stop)
{
k = k + 1;
for(i = -m_ispatial_kwidth; (i<m_ispatial_kwidth+1); i++)
{
for( j = -m_ispatial_kwidth; (j<m_ispatial_kwidth+1); j++)
{
height_idx = x + i;
width_jdx = y + j;
if((height_idx>=0)&&(height_idx<img_height)&&(width_jdx>=0)&&(width_jdx<img_width))
{
temp_weigth = computeweigth(ori_img, i, j, x, y,currentvalue);
totol_weigh = totol_weigh+ temp_weigth;
temp_value = temp_value + ori_img.m_pR[height_idx*img_width+width_jdx]* temp_weigth;
temp_img_x += (height_idx * temp_weigth);
temp_img_y += (width_jdx * temp_weigth);
}
}
}
result = temp_value / totol_weigh;
newx = (int)(temp_img_x/totol_weigh);
newy = (int)(temp_img_y/totol_weigh);
if (abs((unsigned char)result - currentvalue)< 2 )
{
b_stop = true;
}
el
{
x = newx;
y = newy;
currentvalue = (unsigned char)result;
}
}
return (unsigned char)result;
}
/*********************************************************
*
*输入参数:
* ori_img : 原始图像
* x,y : 当前处理点的坐标
* currentvalue : 当前处理点的像素值
* i,j : 由空间核窗宽大小确定的范围索引,相对x,y而言的相对坐标
*
*
*返回值:
* temp_weigth : 点(i,j)对当前处理点(x,y)的权重
*
*/
double CMeanshift::computeweigth(CImage& ori_img, int i,int j,int x, int y,unsigned char currentvalue)
{
CString strTemp;
int img_width = ori_img.GetWidth();
int img_height = ori_img.GetHeigth();
int temp_img_value;
int height_idx = x + i;
int width_jdx = y + j;
temp_img_value = abs(currentvalue-ori_img.m_pR[height_idx*img_width + width_jdx]);
if(temp_img_value >= 5 * m_irange_kwidth)
{
return 0.0;
}
el
{
/*
#if _DEBUG
strTemp.Format("%dmmmm%f",i*i+j*j,m_pspatial_weigth[i*i+j*j]);
AfxMessageBox(strTemp);
strTemp.Format("%dmmmm%f",temp_img_value,m_pspatial_weigth[i*i+j*j]);
AfxMessageBox(strTemp);
#endif
*/
return (m_pspatial_weigth[i*i+j*j] * m_prange_weigth[temp_img_value]);
}
// return temp_weigth;
}