ITK to RTK migration, forward projection issues/questions

Hi. I’m trying to port my ITK DRR renderer to RTK to leverage some of the GPU speedups, but the RTK API and output are considerably different from ITK and I’m not getting very far.

For instance, here’s a a lateral DRR from ITK

And here is what RTK outputs. Ignore the rotation and FOV difference…

The ITK workflow makes sense to me logically:

  1. Resample filter, 3D CT as input, 2D DRR as output.
  2. Use raycast interpolator, set xray source pos, attach to filter.
  3. Filter and interpolator get a transform (AffineTransform in my case)
  4. For each output pixel, interpolator casts a ray, accumulates result.

I’m kinda not grokking how the overall RTK forward projection paradigm works, though.

RTK workflow as I currently have it:

  1. ConstantImageSource.
    SetSize(DRR output size, in px)
    SetSpacing(DRR pixel spacing, in mm)
    SetOrigin(??) - What origin am I setting here? What coordinate space?
    SetConstant(0) - What is this for?
  2. ForwardProjectionImageFilter
    SetInput(0, ConstantImageSource)
    SetInput(1, 3D CT)
  3. Create Reg23ProjectionGeometry
    Set virtual xray source pos, virtual xray detector pos, and DRR direction vectors
    Ultimately I expect to transform these params by the AffineTransform that I use for my ITK DRRs to position my src/det correctly. First things first, though…
  4. ForwardProjection->SetGeometry(reg23geom)
  5. ForwardProjection output to 2D image


  1. Why does it accumulate everything outside the volume to solid white? No matter far back I move my virtual source pos in ITK it never accumulates empty space to white.
  2. What is the relationship of the ConstantImageSource to the forward projector? Is this just a hack to get some output parameters into the filter, or is it actually iterating over the ConstantImageSource space?
  3. Why are output parameters specified via an input to the forward iterator?
  4. What is the relationship between the ConstantImageSource origin to the DRR? What are you actually setting when you set ConstantImageSource origin?
  5. What is the relationship of the ConstantImageSource constant value to anything? Seems not to have any effect.

Any sort of help here would be appreciated. Thanks!

Perhaps it is trying to emulate how X-ray works. If there is only air between source and detector, then detector’s pixel has maximum intensity (white). Maybe you need to invert something there, to get the result you want.

But this is speculation. Someone from the RTK project should be better suited to answering these questions. @simon.rit

1 Like

I suggest you send your questions to the RTK mailing list next time but let me try to answer your questions:

Some information on the geometry is available here. The origin defines the coordinate system of your projection.

This filter creates an image filled with a constant. If you want to start with 0 projections, set it to 0.

Prefer ThreeDCircularProjectionGeometry, Reg23ProjectionGeometry is here for backward compatibility but everything has been moved to its mother class.

It just takes a line integral and values outside the volume are assumed to be 0. Are you working with HUs? That would explain why its “white” outside because 0 corresponds to water in HUs. Transform your HUs to something where air is at 0 (add 1024).

The forward projector accumulates its values to an input on whichi it iterates. When its filled with 0s, this is indeed a way to pass some parameters to the filter but it is also used sometimes to forward project to a non constant image.

This is a design choice we have made very early. A forward projector takes as input 0 the image in which it forwards projects and input 1 the volume it forward projects. A backprojector takes as input 0 the volume in which it backprojects and input 1 the projection it backprojects. I find this more practical than having to set the parameters (origin, spacing, direction) and adding a sum with another image.

The origin of your DRR in the itk::Image sense, i.e., the coordinate of the first pixel of your DRR. Note that the third dimension is ignored since we use a stack of projections.

It does. That’s the value it will start from. The DRR will add values to it.

At some point, we wrapped the ITK interpolator in an RTK forward projector (i.e., the opposite direction of what you’re trying to do). See code here if you’re insterested. It might be helpful for what you’re trying. The code has been removed since.


Awesome, thanks for the answers. Let me digest this stuff, and I’ll follow up on the mailing list.