Проблема с вращением 3D в C / CUDA - PullRequest
0 голосов
/ 03 августа 2011

Я пытаюсь реализовать процедуру трехмерного вращения для стека изображений с использованием C / CUDA (в основном, для ускорения вычислений).Я использовал исходный код ImageJ в качестве основы для кода, поэтому вращение происходит не вокруг источника, а вокруг оси.Есть интересная проблема, с которой я столкнулся.Я реализовал вращение объекта вокруг оси Y без особых проблем.Однако, когда я пытаюсь повернуть вокруг оси X с очень похожим кодом, возникают проблемы.Я заметил, что во вращении X было значительное чередование, например, в этом примере:

http://i.imgur.com/dkecs.png

, которого не было в вращении Y, которое я делал.

Я предоставил ядра CUDA, которые запускаются для вращения вокруг каждой оси (вращение Y - это то, что работает, вращение X - это то, которое дает чередование).Мне было интересно, если кто-нибудь может дать какие-либо предложения относительно того, почему у меня возникнут проблемы с одним, а не с другим, при условии, что они очень похожи в реализации.

РЕДАКТИРОВАТЬ: я сузил проблему до atomicMin ()не работает правильно.zbuffer не изменяется правильно, даже если все смещения установлены правильно.Если кто-нибудь знает, почему это может не сработать, было бы хорошо узнать.

__global__ void rotationY(int *input, int *projArray, int costheta, int sintheta, int width, int height, int depth, int xcenter, int zcenter,
int projectionwidth, int projectionsize, int *zbuffer, int adjCue, int depthCueSurf, int zmax, int zdiff){
int i=threadIdx.x + blockDim.x*blockIdx.x;
int zcostheta;
int zsintheta;
int offset;
int k, z, point, xnew, znew;
int y=i/width;
int x=i-y*width-xcenter;
int xcostheta = x*costheta;
int xsintheta = x*sintheta;
int offsetinit = y*projectionwidth;
zbuffer[i]=32767;
__syncthreads();
for(k=1; k<=depth; k++){
    z = (int)(k-1+.5) - zcenter;
    zcostheta = z*costheta;
    zsintheta = z*sintheta;
    point = i + (k-1)*width*height;
    if(input[point]>0){
        xnew = (xcostheta + zsintheta)/8192 + xcenter;
        znew = (zcostheta - xsintheta)/8192 + zcenter;
        offset = offsetinit + xnew;
        if (offset<0 || offset>=projectionsize) offset = 0;
        atomicMin(&zbuffer[offset],znew);
    }
    __syncthreads();
    if(input[point]>0){
        if(znew<=zbuffer[offset]) projArray[offset] = adjCue*input[point]/100+depthCueSurf*input[point]*(zmax-znew)/zdiff;
    }

}
}

__global__ void rotationX(int *input, int *projArray, int costheta, int sintheta, int width, int height, int depth, int ycenter, int zcenter,
int projectionsize, int *zbuffer, int adjCue, int depthCueSurf, int zmax, int zdiff)    {

int i=threadIdx.x + blockDim.x*blockIdx.x;
int zcostheta;
int zsintheta;
int offset;
int k, z, point, ynew, znew;
int y=i/width;
int x=i-y*width;
y=y-ycenter;
int ycostheta = y*costheta;
int ysintheta = y*sintheta;
zbuffer[i]=32767;
__syncthreads();
for(k=1; k<=depth; k++){
    z = (int)(k-1+.5) - zcenter;
    zcostheta = z*costheta;
    zsintheta = z*sintheta;
    point = i + (k-1)*width*height;
    if(input[point]>0){
        ynew = (ycostheta - zsintheta)/8192 + ycenter;
        znew = (ysintheta + zcostheta)/8192 + zcenter;
        offset = x + ynew*width;
        if (offset<0 || offset>=projectionsize) offset = 0;
        atomicMin(&zbuffer[offset], znew);
    }
    __syncthreads();
    if(input[point]>0){
        if(znew<=zbuffer[offset]) projArray[offset] = adjCue*input[point]/100+depthCueSurf*input[point]*(zmax-znew)/zdiff;
    }
}
}

1 Ответ

1 голос
/ 04 августа 2011

Параметр projectionwidth отсутствует в прототипе функции вращенияX. Это мой лучший кандидат на ошибку прямо сейчас.

enter image description here

...