在图像的ROI内随机漫步

时间:2013-09-25 13:57:22

标签: c++ image-processing montecarlo

我正在研究扩散核磁共振成像项目并且有一个我需要帮助的c ++问题。

背景: 我有一个.nii图像作为参考,我希望控制节点(它是样条曲线的一部分)在图像的约束ROI内执行随机游走。为了澄清:.nii图像是一个显示大脑白质(WM)的模板,我想要一个带有4个控制节点的样条线在这个模板中随机移动,直到它们达到最小化成本函数的状态。目前我正在做的只是更新一个随机控制节点,根据高斯分布在随机方向上移动,然后检查它是在WM内部还是外部,如果在WM之外,则重新绘制。但这可能导致许多不必要的抽奖,我想避免。

我的问题: 有没有更好的方法来做到这一点?我有一个想法是将我的ROI的所有像素坐标收集到一个单独的数组或矩阵中,我可以从该矩阵的索引中绘制出来?如果我想用四个全新的控制点重新初始化样条曲线,这个方法也会有所帮助。 (我还需要在将来实施)

目前使用的方法代码:

blitz::Array<Catmull,1> FIBERs;         // Fiber with control nodes (knots) which I want to move
NIFTI<INT16>* niiWM = new NIFTI<INT16>; // .nii Image which contains WM mask
void SimulatedAnnealing_OneStep( void )
{
    iF = floor( FIBERs.extent(0)*uniformGen.random());  //  select randomly a FIBER 
    NewProposal(iF);
    Pen = CheckWM(iF);
    while(Pen >= 1){
        NewProposal(iF);
    Pen = CheckWM(iF);
    } 
}
void NewProposal( int ifff)
{
    static int              iK;
    static POINT            delta;

    delta.Set( MOVE_sigma*normalGen.random(), MOVE_sigma*normalGen.random(), 0 );       
    iK = floor(uniformGen.random()*6); 

    if( iK==2 || iK==3 ) // Moving the middle control points within the WM 
    {   // FIBERs(ifff) is a randomly selected fiber (outside this method) which we are moving
        FIBERs(ifff).KNOTs[iK].x += delta.x;
        FIBERs(ifff).KNOTs[iK].y += delta.y;
        FIBERs(ifff).KNOTs[iK].z += delta.z;
        FIBERs(ifff).KNOTs[iK].x =  fmin( fmax( FIBERs(ifff).KNOTs[iK].x,0), Nx );
        FIBERs(ifff).KNOTs[iK].y =  fmin( fmax( FIBERs(ifff).KNOTs[iK].y,  0), Ny );
        FIBERs(ifff).KNOTs[iK].z =  fmin( fmax( FIBERs(ifff).KNOTs[iK].z, 0), Nz ); 
    }   
}

int CheckWM( int iff )
{
int j,Pe;
int Vx, Vy, Vz;

Pe = 0;

for(j=0; j<FIBERs(iff).P.extent(0) ;j++){           // Loop through the segments on the curve
    Vx = floor( FIBERs(iff).P(j).x );               // midpoint of the segment
    Vy = floor( FIBERs(iff).P(j).y );
    Vz = floor( FIBERs(iff).P(j).z );

    if ((*niiWM->img)(Vx,Vy,Vz) == 0){              // Penalize when outside the WM
    Pe += 1;}
     }
     return Pe;     
}

我希望这是足够的信息。谢谢你的时间。

1 个答案:

答案 0 :(得分:0)

你有什么类型的成本函数(如果我从你的代码中读取它只是不属于白质的像素总和?)?如果它是平滑且连续的,你可以尝试梯度下降来找到最小值(因为你看起来离散,但是,有没有办法让你近似梯度下降?)。这应该比随机游走更有效。

如果保持随机性非常重要,那么在不进行大量重新绘制的情况下执行此操作的最佳方法是重新规范您可以选择的分布范围。如果我理解正确,你已经有了白质面具,所以应该允许你这样做的一种方法是:

1。)根据以当前位置为中心的高斯分配所有白质像素的概率

2.)重新规范这些概率,使它们总和为1

3.)从均匀分布中拉出一个随机数,找出它对应的像素

4。)将控制点移到那里

因此,例如,如果您有四个可能的白质像素,则可以使用概率0.1, 0.17, 0.2, and 0.23移动到相应的位置(x1,y1), (x2,y2), (x3, y3), (x4, y4),其中包含所有其他可能的像素(基于您的高斯随机步骤)非白质像素将迫使您重新绘制,然后您将通过除以它们的总和(在这种情况下为0.7)来重新缩放概率。然后从统一分布中拉出一个随机数(假设你拉了0.3)。这将基于重新规范化的概率对应于第二个点(x2, y2),您可以将控制点移到那里。

正如您所看到的,这需要执行相当多的计算步骤,但确保您只需要拉一个随机目标进行更新;因此,性能的任何改进都取决于这些额外计算的相对成本与实际重新采样的频率。我也写得非常快,所以你可能能够提出一种更有效的方法来将随机选择的范围限制为只有好的像素。