什么是积分体
积分体是根据二维图像中的积分图在三维中的延伸得到,目的是快速计算局部的像素和。有关积分图的知识可以自行百度,相信看完你就明白。
通过积分体可以快速计算出一个三维滤波核(3x3x3)对应区域的像素值之和,因此利用积分体可以快速计算出某个体素邻域内的局部均值和局部方差。
均值和方差快速计算公式
根据积分体的定义,可以快速计算出式中的和
代码
积分体计算
void GetIntegralVol(uchar* Vol, uint* IntegralVol, int width, int height, int depth)
{
memset(IntegralVol, 0, (width + 1) * (height + 1) * sizeof(uint));//积分体中第一张切片均为0
uint* slice = new uint[(width + 1) * (height + 1)]();//用来记录当前切面的积分图
memset(slice, 0, (width + 1) * sizeof(uint));//第一行均为0
for (int d = 0; d < depth; d++)
{
uchar* Src = Vol + d * width * height;//原始体数据中每张切面的初始位置
uint* Integral = IntegralVol + (d + 1) * (width + 1) * (height + 1);//积分体中每张切面的初始位置
memset(Integral, 0, (width + 1) * sizeof(uint));//积分图中第一行均为0
for (int h = 0; h < height; h++)
{
uint* LinePL = slice + h * (width + 1) + 1;//当前切面积分图中上一行的位置
uint* LinePD = slice + (h + 1) * (width + 1) + 1;//当前切面积分图中的当前位置
LinePD[-1] = 0;//积分图中每一行的第一列的值都为0
uchar* ImgPS = Src + h * width;//原始体数据当前切片中每一行的初始位置
uint* ImgPD = Integral + (h + 1) * (width + 1) + 1;//积分体中当前切面的当前位置
ImgPD[-1] = 0;//每一行的第一列的值均为0
uint* ImgPL = IntegralVol + (width + 1) * ((height + 1) * d + h + 1) + 1;//积分体中当前切面的上一切面的同一位置
for (int w = 0, sum = 0; w < width; w++)
{
sum += ImgPS[w];//切面图中每一行的累加和
LinePD[w] = LinePL[w] + sum;//当前切面的积分图
ImgPD[w] = LinePD[w] + ImgPL[w];//更新积分体=当前切面的积分图+前一切面的积分体
}
}
}
delete[]slice;
}
积分体使用
//积分体两个切面四行的行首位置
ImgS1LineP1:第一切面的第一行
ImgS1LineP2:第一切面的第二行
ImgS2LineP1:第二切面的第一行
ImgS2LineP2:第二切面的第二行
//求和
SUM=ImgS1LineP1[w2]-ImgS1LineP1[w1]+ImgS1LineP2[w1]-ImgS1LineP2[w2]+
ImgS2LineP1[w1]-ImgS2LineP1[w2]+ImgS2LineP2[w2]-ImgS2LineP2[w1];