GreycLab/CImg

apply 3d rotation to image

Closed this issue · 5 comments

uxhub commented

Hi all,
What's the best way to apply a 3d rotation to a 3d image with CImg ?
Best regards,

Maybe something like this ?
I've not tested, just an idea. Should be working, but take care of the final image dimensions, etc...

#include "CImg.h"
using namespace cimg_library;

int main(int argc, char **argv) {

  const CImg<> in3d("input3d.tiff");
  const float
    rx = 1,                   // (rx,ry,rz) is the rotation axis
    ry = 0,
    rz = 0,
    theta = 45*cimg::PI/180,  // 'theta' is the angle in radian
    w2 = 0.5f*in3d.width(),
    h2 = 0.5f*in3d.height(),
    d2 = 0.5f*in3d.depth();
  const CImg<> rot = CImg<>::rotation_matrix(rx,ry,rz,-theta);

  CImg<> out3d(in3d);
  cimg_forXYZ(in3d,x,y,z) {
    const float
      X = w2 + (x - w2)*rot(0,0) + (y - h2)*rot(1,0) + (z - d2)*rot(2,0),
      Y = h2 + (x - w2)*rot(0,1) + (y - h2)*rot(1,1) + (z - d2)*rot(2,1),
      Z = d2 + (x - w2)*rot(0,2) + (y - h2)*rot(1,2) + (z - d2)*rot(2,2);
    cimg_forC(in3d,c) out3d(x,y,z,c) = in3d.linear_atXYZ(X,Y,Z,c,0);
  }

  (in3d,out3d).display();

  return 0;
}

uxhub commented

Thanks, I will try, but it seems ok.
May I suggest a "apply 3d affine transform" function ? ;)
Regards,

That's a good idea indeed.
The tests I've done also made me realize that the method CImg<T>::rotation_matrix() didn't return the correct rotation matrix (but its inverse!). I've fixed the issue with latest commit, so you probably want to update the sources before using it.

EDIT : Other change, the last parameter to CImg<T>::rotation_matrix() is now expressed in degrees.

OK, I've done some improvements this morning, and now, there is a new CImg<T>::rotate() that is able to rotate a volumetric image around a 3d axis, with an arbitrary angle.
Check the doc : http://cimg.eu/reference/structcimg__library_1_1CImg.html#ae6242d4be56d39c57f10e28fe417e04b

Feel free to test and give feedback. Thanks.

uxhub commented

Well it's perfect ! and I didn't noticed any bug...
You may also make a rotate function taking a rotation matrix as parameter.
Great job as usual !
Regards