summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/astra/ParallelBeamBlobKernelProjector2D.h7
-rw-r--r--include/astra/ParallelBeamBlobKernelProjector2D.inl267
-rw-r--r--src/ParallelBeamBlobKernelProjector2D.cpp92
3 files changed, 163 insertions, 203 deletions
diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.h b/include/astra/ParallelBeamBlobKernelProjector2D.h
index ecf71ef..a718f56 100644
--- a/include/astra/ParallelBeamBlobKernelProjector2D.h
+++ b/include/astra/ParallelBeamBlobKernelProjector2D.h
@@ -215,7 +215,12 @@ protected:
float32 m_fBlobSampleRate; //< At which interval are the inserted blob values evaluated?
int m_iBlobSampleCount; //< Number of evaluated blob samples
float32* m_pfBlobValues; //< Evaluated blob values
- float32* m_pfBlobValuesNeg; //< Evaluated blob values
+
+ /** Internal policy-based projection of a range of angles and range.
+ * (_i*From is inclusive, _i*To exclusive) */
+ template <typename Policy>
+ void projectBlock_internal(int _iProjFrom, int _iProjTo,
+ int _iDetFrom, int _iDetTo, Policy& _policy);
};
diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.inl b/include/astra/ParallelBeamBlobKernelProjector2D.inl
index 467e066..203eb51 100644
--- a/include/astra/ParallelBeamBlobKernelProjector2D.inl
+++ b/include/astra/ParallelBeamBlobKernelProjector2D.inl
@@ -27,186 +27,151 @@ $Id$
*/
-
-//----------------------------------------------------------------------------------------
-// PROJECT ALL
template <typename Policy>
void CParallelBeamBlobKernelProjector2D::project(Policy& p)
{
- for (int iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
- for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
- projectSingleRay(iAngle, iDetector, p);
- }
- }
+ projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(),
+ 0, m_pProjectionGeometry->getDetectorCount(), p);
}
-
-//----------------------------------------------------------------------------------------
-// PROJECT SINGLE PROJECTION
template <typename Policy>
void CParallelBeamBlobKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
{
- for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
- projectSingleRay(_iProjection, iDetector, p);
- }
+ projectBlock_internal(_iProjection, _iProjection + 1,
+ 0, m_pProjectionGeometry->getDetectorCount(), p);
}
-
-
-//----------------------------------------------------------------------------------------
-// PROJECT SINGLE RAY
template <typename Policy>
void CParallelBeamBlobKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
{
- ASTRA_ASSERT(m_bIsInitialized);
-
- int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
-
- // POLICY: RAY PRIOR
- if (!p.rayPrior(iRayIndex)) return;
-
- // get values
- float32 t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
- float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
- if (theta >= 7*PIdiv4) theta -= 2*PI;
-
- bool flip = false;
+ projectBlock_internal(_iProjection, _iProjection + 1,
+ _iDetector, _iDetector + 1, p);
+}
- if (theta >= 3*PIdiv4) {
- theta -= PI;
- t = -t;
- flip = true;
+//----------------------------------------------------------------------------------------
+// PROJECT BLOCK - vector projection geometry
+template <typename Policy>
+void CParallelBeamBlobKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p)
+{
+ // variables
+ float32 detX, detY, x, y, c, r, update_c, update_r, offset, invBlobExtent, inv_pixelLengthX, inv_pixelLengthY, weight, d;
+ int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, colCount, rowCount, detCount;
+ int col_left, col_right, row_top, row_bottom, index;
+ const SParProjection * proj = 0;
+
+ // get vector geometry
+ const CParallelVecProjectionGeometry2D* pVecProjectionGeometry;
+ if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)) {
+ pVecProjectionGeometry = dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)->toVectorGeometry();
+ } else {
+ pVecProjectionGeometry = dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry);
}
+ // precomputations
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+ colCount = m_pVolumeGeometry->getGridColCount();
+ rowCount = m_pVolumeGeometry->getGridRowCount();
+ detCount = pVecProjectionGeometry->getDetectorCount();
+
+ // loop angles
+ for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
+
+ proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle];
+
+ bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY);
+ if (vertical) {
+ update_c = -m_pVolumeGeometry->getPixelLengthY() * (proj->fRayX/proj->fRayY) * inv_pixelLengthX;
+ float32 normR = sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX);
+ invBlobExtent = m_pVolumeGeometry->getPixelLengthY() / abs(m_fBlobSize * normR / proj->fRayY);
+ } else {
+ update_r = -m_pVolumeGeometry->getPixelLengthX() * (proj->fRayY/proj->fRayX) * inv_pixelLengthY;
+ float32 normR = sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX);
+ invBlobExtent = m_pVolumeGeometry->getPixelLengthX() / abs(m_fBlobSize * normR / proj->fRayX);
+ }
- if (theta <= PIdiv4) { // -pi/4 <= theta <= pi/4
-
- // precalculate sin, cos, 1/cos
- float32 sin_theta = sin(theta);
- float32 cos_theta = cos(theta);
- float32 inv_cos_theta = 1.0f / cos_theta;
-
- // precalculate other stuff
- float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
- float32 updatePerRow = sin_theta * lengthPerRow;
- float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
- float32 pixelLengthX_over_blobSize = m_pVolumeGeometry->getPixelLengthX() / m_fBlobSize;
-
- // some variables
- int row, col, xmin, xmax;
- float32 P, x, d;
-
- // calculate P and x for row 0
- P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
- x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f;
-
- // for each row
- for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+ // loop detectors
+ for (iDetector = _iDetFrom; iDetector < _iDetTo; ++iDetector) {
- // calculate extent
- xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f);
- xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f);
-
- // add pixels
- for (col = xmin; col <= xmax; col++) {
- if (col >= 0 && col < m_pVolumeGeometry->getGridColCount()) {
- //d = abs(x - col) * pixelLengthX_over_blobSize;
- //index = (int)(d*m_iBlobSampleCount+0.5f);
- //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerRow;
-
- float32 fWeight;
- int index;
- if ((x >= col) ^ flip) {
- d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta;
- index = (int)(d*m_iBlobSampleCount+0.5f);
- fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
- } else {
- d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta;
- index = (int)(d*m_iBlobSampleCount+0.5f);
- fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)];
- }
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
- int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
- // POLICY: PIXEL PRIOR + ADD + POSTERIOR
- if (p.pixelPrior(iVolumeIndex)) {
- p.addWeight(iRayIndex, iVolumeIndex, fWeight);
- p.pixelPosterior(iVolumeIndex);
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ detX = proj->fDetSX + (iDetector+0.5f) * proj->fDetUX;
+ detY = proj->fDetSY + (iDetector+0.5f) * proj->fDetUY;
+
+ // vertically
+ if (vertical) {
+
+ // calculate x for row 0
+ x = detX + (proj->fRayX/proj->fRayY)*(m_pVolumeGeometry->pixelRowToCenterY(0)-detY);
+ c = (x - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f;
+
+ // for each row
+ for (row = 0; row < rowCount; ++row, c += update_c) {
+
+ col_left = int(c - 0.5f - m_fBlobSize);
+ col_right = int(c + 0.5f + m_fBlobSize);
+
+ if (col_left < 0) col_left = 0;
+ if (col_right > colCount-1) col_right = colCount-1;
+
+ // for each column
+ for (col = col_left; col <= col_right; ++col) {
+
+ offset = abs(c - float32(col)) * invBlobExtent;
+ index = (int)(offset*m_iBlobSampleCount+0.5f);
+ weight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
+
+ iVolumeIndex = row * colCount + col;
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, weight);
+ p.pixelPosterior(iVolumeIndex);
+ }
}
}
}
- // update P and x
- P += updatePerRow;
- x += updatePerRow * inv_pixelLengthX;
- }
+ // horizontally
+ else {
- } else { // pi/4 < theta < 3pi/4
-
- // precalculate sin cos
- float32 sin_90_theta = sin(PIdiv2-theta);
- float32 cos_90_theta = cos(PIdiv2-theta);
- float32 inv_cos_90_theta = 1.0f / cos_90_theta;
-
- // precalculate other stuff
- float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_cos_90_theta;
- float32 updatePerCol = sin_90_theta * lengthPerCol;
- float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
- float32 pixelLengthY_over_blobSize = m_pVolumeGeometry->getPixelLengthY() / m_fBlobSize;
-
- // some variables
- int row, col, xmin, xmax;
- float32 P,x, d;
-
- // calculate P and x for col 0
- P = (sin_90_theta * m_pVolumeGeometry->pixelColToCenterX(0) - t) * inv_cos_90_theta;
- x = (P - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f;
-
- // for each col
- for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
-
- // calculate extent
- xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f);
- xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f);
-
- // add pixels
- for (row = xmin; row <= xmax; row++) {
- if (row >= 0 && row < m_pVolumeGeometry->getGridRowCount()) {
- //d = abs(x - row) * pixelLengthY_over_blobSize;
- //int index = (int)(d*m_iBlobSampleCount+0.5f);
- //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerCol;
-
- float32 fWeight;
- int index;
- if ((x <= row) ^ flip) {
- d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta;
- index = (int)(d*m_iBlobSampleCount+0.5f);
- fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
- } else {
- d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta;
- index = (int)(d*m_iBlobSampleCount+0.5f);
- fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)];
- }
+ // calculate y for col 0
+ y = detY + (proj->fRayY/proj->fRayX)*(m_pVolumeGeometry->pixelColToCenterX(0)-detX);
+ r = (m_pVolumeGeometry->getWindowMaxY() - y) * inv_pixelLengthY - 0.5f;
+ // for each col
+ for (col = 0; col < colCount; ++col, r += update_r) {
- int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
- // POLICY: PIXEL PRIOR + ADD + POSTERIOR
- if (p.pixelPrior(iVolumeIndex)) {
- p.addWeight(iRayIndex, iVolumeIndex, fWeight);
- p.pixelPosterior(iVolumeIndex);
- }
- }
- }
+ row_top = int(r - 0.5f - m_fBlobSize);
+ row_bottom = int(r + 0.5f + m_fBlobSize);
- // update P and x
- P += updatePerCol;
- x += updatePerCol * inv_pixelLengthY;
- }
+ if (row_top < 0) row_top = 0;
+ if (row_bottom > rowCount-1) row_bottom = rowCount-1;
- }
-
- // POLICY: RAY POSTERIOR
- p.rayPosterior(iRayIndex);
+ // for each column
+ for (row = row_top; row <= row_bottom; ++row) {
+ offset = abs(r - float32(row)) * invBlobExtent;
+ index = (int)(offset*m_iBlobSampleCount+0.5f);
+ weight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
+
+ iVolumeIndex = row * colCount + col;
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, weight);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+ } // end loop angles
}
diff --git a/src/ParallelBeamBlobKernelProjector2D.cpp b/src/ParallelBeamBlobKernelProjector2D.cpp
index 3253f88..d030576 100644
--- a/src/ParallelBeamBlobKernelProjector2D.cpp
+++ b/src/ParallelBeamBlobKernelProjector2D.cpp
@@ -102,7 +102,7 @@ bool CParallelBeamBlobKernelProjector2D::_check()
// check base class
ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamBlobKernelProjector2D", "Error in Projector2D initialization");
- ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamBlobKernelProjector2D", "Unsupported projection geometry");
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamBlobKernelProjector2D", "Unsupported projection geometry");
ASTRA_CONFIG_CHECK(m_iBlobSampleCount > 0, "ParallelBeamBlobKernelProjector2D", "m_iBlobSampleCount should be strictly positive.");
ASTRA_CONFIG_CHECK(m_pfBlobValues, "ParallelBeamBlobKernelProjector2D", "Invalid Volume Geometry Object.");
@@ -156,16 +156,6 @@ bool CParallelBeamBlobKernelProjector2D::initialize(const Config& _cfg)
m_pfBlobValues[i] = values[i];
}
- // Required: KernelValues
- node2 = node->getSingleNode("KernelValuesNeg");
- ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelValuesNeg tag specified.");
- vector<float32> values2 = node2->getContentNumericalArray();
- ASTRA_CONFIG_CHECK(values2.size() == (unsigned int)m_iBlobSampleCount, "BlobProjector", "Number of specified values doesn't match SampleCount.");
- m_pfBlobValuesNeg = new float32[m_iBlobSampleCount];
- for (int i = 0; i < m_iBlobSampleCount; i++) {
- m_pfBlobValuesNeg[i] = values2[i];
- }
-
}
// success
@@ -228,44 +218,44 @@ void CParallelBeamBlobKernelProjector2D::computeSingleRayWeights(int _iProjectio
// Splat a single point
std::vector<SDetector2D> CParallelBeamBlobKernelProjector2D::projectPoint(int _iRow, int _iCol)
{
- float32 x = m_pVolumeGeometry->pixelColToCenterX(_iCol);
- float32 y = m_pVolumeGeometry->pixelRowToCenterY(_iRow);
-
- std::vector<SDetector2D> res;
- // loop projectors and detectors
- for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
-
- // get projection angle
- float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
- if (theta >= 7*PIdiv4) theta -= 2*PI;
- bool inverse = false;
- if (theta >= 3*PIdiv4) {
- theta -= PI;
- inverse = true;
- }
-
- // calculate distance from the center of the voxel to the ray though the origin
- float32 t = x * cos(theta) + y * sin(theta);
- if (inverse) t *= -1.0f;
-
- // calculate the offset on the detectorarray (in indices)
- float32 d = m_pProjectionGeometry->detectorOffsetToIndexFloat(t);
- int dmin = (int)ceil(d - m_fBlobSize);
- int dmax = (int)floor(d + m_fBlobSize);
-
- // add affected detectors to the list
- for (int i = dmin; i <= dmax; ++i) {
- if (d >= 0 && d < m_pProjectionGeometry->getDetectorCount()) {
- SDetector2D det;
- det.m_iAngleIndex = iProjection;
- det.m_iDetectorIndex = i;
- det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
- res.push_back(det);
- }
- }
- }
-
- // return result vector
- return res;
-
+ // float32 x = m_pVolumeGeometry->pixelColToCenterX(_iCol);
+ // float32 y = m_pVolumeGeometry->pixelRowToCenterY(_iRow);
+
+ // std::vector<SDetector2D> res;
+ // // loop projectors and detectors
+ // for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // // get projection angle
+ // float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ // if (theta >= 7*PIdiv4) theta -= 2*PI;
+ // bool inverse = false;
+ // if (theta >= 3*PIdiv4) {
+ // theta -= PI;
+ // inverse = true;
+ // }
+
+ // // calculate distance from the center of the voxel to the ray though the origin
+ // float32 t = x * cos(theta) + y * sin(theta);
+ // if (inverse) t *= -1.0f;
+
+ // // calculate the offset on the detectorarray (in indices)
+ // float32 d = m_pProjectionGeometry->detectorOffsetToIndexFloat(t);
+ // int dmin = (int)ceil(d - m_fBlobSize);
+ // int dmax = (int)floor(d + m_fBlobSize);
+
+ // // add affected detectors to the list
+ // for (int i = dmin; i <= dmax; ++i) {
+ // if (d >= 0 && d < m_pProjectionGeometry->getDetectorCount()) {
+ // SDetector2D det;
+ // det.m_iAngleIndex = iProjection;
+ // det.m_iDetectorIndex = i;
+ // det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ // res.push_back(det);
+ // }
+ // }
+ // }
+
+ // // return result vector
+ // return res;
+ return std::vector<SDetector2D>();
}