下面的 openCL 代码工作得很好,速度也很快,但我的印象是我在 openCL 障碍和索引混合方面遗漏了一些东西;我知道这不是很容易理解,它是我正在研究的 CBCT 重建的核心;结局图(ReturnMatrice 看起来有点困惑)。
__kernel void
ReconstructionGPU(
__global float* Matrice,
__global float* ReturnMatrice,
__global short* ReturnCheckImage,
__constant float* _dLocArraiAngoliSen,
__constant float* _dLocArraiAngoliCos,
__constant float* Cos_Tilt_in_Rad,
__constant float* Sin_Tilt_in_Rad,
__constant float* iTilt,
__constant float* _iOffsetU,
__constant float* _iOffsetV,
__constant int* iSizeX,
__constant int* iSizeY,
__constant int* iSizeZ,
__constant int* iSizeImgX,
__constant int* iSizeImgY,
__constant float* _fDSO,
__constant float* _fDSD,
__constant float* m_fSizeVoxelX,
__constant float* m_fSizeVoxelY,
__constant float* m_fPixelSensoreDim,
__constant int* Loop,
__constant int* Axial,
__constant int* Padding
)
{
private int _iLocSizeX = iSizeX[0]; // Detector X
private int _iLocSizeY = iSizeY[0]; // Detector Y
private int _iLocSizeImage = _iLocSizeX * _iLocSizeY; // Dimensione Immagine
private int _iSizeMezziX; // EmiMatrix X
_iSizeMezziX = (iSizeX[0] / 2 );
private int _iSizeMezziY;
_iSizeMezziY = (iSizeY[0] / 2 ); // EmiMatrix Y
private int _iSizeMezziDetX; // Emidetector X
_iSizeMezziDetX = (iSizeImgX[0] / 2 );
private int _iSizeMezziDetY;
_iSizeMezziDetY = (iSizeImgY[0] / 2 ); // Emidetector Y
private float _iSizeMezziYQuadro = ((_iSizeMezziX - Padding[0]) * (_iSizeMezziY - Padding[0])); //Border
private float kySen = 0;
private float kyCos = 0;
private float CoordY_Piu_OffsetU = 0;
private float CoordZ_Piu_OffsetV = 0;
private float fDist_Y_inMmObj = 0;
private float fDist_Z_inMmObj = 0;
private float fDSDinMmY = 0;
private float fDSDinMmZ = 0;
private float fDSDinMmYPiu_AngoloTilt = 0;
private float fDSDinMmZPiu_AngoloTilt = 0;
private float _ValImage = 0;
private int ValY = 0;
private int ValZ = 0;
private int _iTempx = 0;
private int _iTempy = 0;
private int _Index = 0;
private int z = 0;
private int zMenoAxial0 = 0;
private float zPerIlockSizeImage = 0;
private float TempYPerIlockSizeX = 0;
private float zPiuTyLoc = 0;
private float zMenoAxTyLoc = 0;
private int m_y;
private int m_x;
private int y;
private int x;
private int m_z = get_global_id(2);
z = m_z + Axial[0];
m_y = get_global_id(1);
m_x = get_global_id(0);
y = (m_y - _iSizeMezziY ) ;
x = (m_x - _iSizeMezziX) ;
CoordZ_Piu_OffsetV = -_iSizeMezziX + z + _iOffsetV[0];
fDist_Z_inMmObj = CoordZ_Piu_OffsetV * m_fSizeVoxelX[0];
zMenoAxial0 = (z - Axial[0] ) * _iLocSizeImage ;
zPerIlockSizeImage = z * _iLocSizeImage;
kySen = (_dLocArraiAngoliSen[Loop[0]] * (y)) ;
kyCos = (_dLocArraiAngoliCos[Loop[0]] * (y)) ;
CoordY_Piu_OffsetU = y - _iOffsetU[0];
fDist_Y_inMmObj = (CoordY_Piu_OffsetU * m_fSizeVoxelY[0]); // Distanza Y in millimetri del voxel in esame nel volume ricostruito
fDSDinMmY = 0;
fDSDinMmYPiu_AngoloTilt = 0;
ValY = 0;
fDSDinMmZ = 0;
fDSDinMmZPiu_AngoloTilt = 0;
ValZ = 0;
_iTempx = ((_iSizeMezziX + (_dLocArraiAngoliCos[Loop[0]] * x) - kySen)); // Calcolo coordinate X
_iTempy = ((_iSizeMezziY + (_dLocArraiAngoliSen[Loop[0]] * x) + kyCos)); // Calcolo coordinate Y
// Calcoli salti per assegnazione matrice ricostruita
TempYPerIlockSizeX = _iTempy * iSizeX[0];
zPiuTyLoc = zPerIlockSizeImage + TempYPerIlockSizeX;
zMenoAxTyLoc = zMenoAxial0 + TempYPerIlockSizeX;
if (_iTempy >= iSizeY - Padding[0] || _iTempx >= iSizeX - Padding[0] || _iTempy< 0 || _iTempx< 0 ||
(((_iTempx - _iSizeMezziX) * (_iTempx - _iSizeMezziX)) + ((_iTempy - _iSizeMezziY) * (_iTempy - _iSizeMezziY))) > _iSizeMezziYQuadro)
{ }
else
{
//float fKval = (_fDSO[0] - (x * m_fSizeVoxelX[0]));
float fKval = (_fDSO[0] - (x * m_fPixelSensoreDim[0]));
fDSDinMmY = ((fDist_Y_inMmObj* _fDSD[0]) / fKval); // Distanza Y del pixel in esame rapportata a DSD in millimetri
fDSDinMmZ = ((fDist_Z_inMmObj* _fDSD[0]) / fKval); // Distanza DSD in millimetri
if (iTilt != 0)
{
fDSDinMmYPiu_AngoloTilt = (fDSDinMmY * Cos_Tilt_in_Rad[0] +0.5f); // Calcolo della Coordinata che tiene conto anche dell'angolo di inclinazione del sensore
ValY = (((fDSDinMmYPiu_AngoloTilt / m_fPixelSensoreDim[0] ) + _iSizeMezziDetX)+0.5f); // Distanza in pixel del pixel in esame sul detector
fDSDinMmZPiu_AngoloTilt = (fDSDinMmZ + (fDSDinMmZ * Sin_Tilt_in_Rad[0])+0.5f); // Calcolo della Coordinata che tiene conto anche dell'angolo di inclinazione del sensore
ValZ = (((fDSDinMmZPiu_AngoloTilt / m_fPixelSensoreDim[0]) + _iSizeMezziDetY)+0.5f); // Distanza in pixel del pixel in esame sul detector
}
else
{
ValY = ((fDSDinMmY / m_fPixelSensoreDim[0]) + _iSizeMezziDetX+0.5f); // Distanza in pixel del pixel in esame sul detector
ValZ = ((fDSDinMmZ / m_fPixelSensoreDim[0]) + _iSizeMezziDetY+0.5f); // Distanza in pixel del pixel in esame sul detector
}
if (ValY >= 0 && ValY < iSizeImgX[0] && ValZ >= 0 && ValZ < iSizeImgY[0])
{
_Index = ((ValZ * iSizeImgX[0]) + ValY);
_ValImage = (float)Matrice[_Index];// Pixel dell'immagine con coordinate calcolate da ValX e ValY
}
else
{
_ValImage = 0; // Pixel dell'immagine con coordinate calcolate da ValX e ValY
}
barrier(CLK_LOCAL_MEM_FENCE);
ReturnMatrice[(int)zMenoAxTyLoc + _iTempx] += _ValImage; //ValImgPesato
_ValImage = 0;
}
}