C/CUDA を使用して画像スタックの 3D 回転ルーチンを実装しようとしています (主に計算時間を短縮するため)。コードのベースとして ImageJ ソース コードを使用したため、回転は原点を中心に自由に行われるのではなく、軸に沿って行われます。しかし、私が遭遇した興味深い問題があります。Y 軸を中心としたオブジェクトの回転をほとんど問題なく実装しました。ただし、非常によく似たコードで X 軸を中心に回転しようとすると、問題が発生します。X 回転で、次の例のように顕著な縞模様があることに気付きました。
これは、私が行っていた Y 回転では発生していませんでした。
各軸の周りの回転を実行するために実行される CUDA カーネルを提供しました (rotationY は動作するもので、rotationX はストライピングを行うものです)。実装が非常に似ている場合、一方の問題が発生し、他方の問題が発生しない理由について、誰かが何か提案を提供できるかどうか疑問に思っていました。
編集:問題を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;
}
}
}