- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please explain the difference between the coordinate systems used by ipprWarpAffine and ipprResize.
In the ipprResize documentation, it says “The right coordinate system (RCS) is used here.”. What is meant by that?
Consider a 2x2x2 volume.
Plane 0 has (x,y,z) coordinates:
000 100
010 110
Plane 1 has (x,y,z) coordinates:
001 101
011 111
If I use ipprWarpAffine with (x,y,z) scale factors of 5 (and no translation), I get a 6x6x6 volume since the coordinates above trivially get mapped to {000 500 050 550} in output plane 0 and {005 505 055 555} in output plane 5 (the rest are interpolated).
If I use ipprResize with (x,y,z) scale factors of 5 (and no translation), it wants me to have an output volume size of (10,10,10).
bool IntelFuncs::TestResizeImage() { int i, x, y, z; const int dim = 2; const int dimNew = 10; std::vector<unsigned short> src ={100, 100, 100, 100, 200, 200, 200, 200}; std::vector<unsigned short> dst(dimNew*dimNew*dimNew); ASSERT(static_cast<int>(src.size()) == dim*dim*dim); i = 0; for (z=0; z<dim; z++) { TRACE(_T("#################### Original Slice %d\n"), z); for (y=0; y<dim; y++) { for (x=0; x<dim; x++, i++) { TRACE(_T("%d "), src); } TRACE(_T("\n")); } } IppStatus status; IpprVolume srcVol ={dim, dim, dim}; IpprCuboid srcVOI ={0, 0, 0, dim, dim, dim}; int srcStep = dim*sizeof(unsigned short); int srcPlaneStep = dim*dim*sizeof(unsigned short); int dstStep = dimNew*sizeof(unsigned short); int dstPlaneStep = dimNew*dimNew*sizeof(unsigned short); double xFactor=5.0, yFactor=5.0, zFactor=5.0, xShift=0.0, yShift=0.0, zShift=0.0; int nInterp = IPPI_INTER_LINEAR; IpprCuboid dstVOI ={0, 0, 0, 0, 0, 0}; status = ipprGetResizeCuboid(srcVOI, &dstVOI, xFactor, yFactor, zFactor, xShift, yShift, zShift, nInterp); ASSERT(dstVOI.width == dimNew && dstVOI.height == dimNew && dstVOI.depth == dimNew); //It wants me to have a dstVOI of size (10,10,10) int bufSize = 0; status = ipprResizeGetBufSize(srcVOI, dstVOI, 1, nInterp, &bufSize); Ipp8u* pBuffer = ippsMalloc_8u(bufSize); status = ipprResize_16u_C1V(src.data(), srcVol, srcStep, srcPlaneStep, srcVOI, dst.data(), dstStep, dstPlaneStep, dstVOI, xFactor, yFactor, zFactor, xShift, yShift, zShift, nInterp, pBuffer); i = 0; for (z=0; z<dimNew; z++) { TRACE(_T("#################### New Slice %d\n"), z); for (y=0; y<dimNew; y++) { for (x=0; x<dimNew; x++, i++) { TRACE(_T("%d "), dst); } TRACE(_T("\n")); } } ippsFree(pBuffer); return false; }
This gives output:
#################### Original Slice 0
100 100
100 100
#################### Original Slice 1
200 200
200 200
#################### New Slice 0
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
#################### New Slice 1
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
#################### New Slice 2
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
#################### New Slice 3
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
120 120 120 120 120 120 120 120 120 120
#################### New Slice 4
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
140 140 140 140 140 140 140 140 140 140
#################### New Slice 5
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
160 160 160 160 160 160 160 160 160 160
#################### New Slice 6
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
180 180 180 180 180 180 180 180 180 180
#################### New Slice 7
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
#################### New Slice 8
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
#################### New Slice 9
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
200 200 200 200 200 200 200 200 200 200
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I forgot to mention I am using IPP 9.0.3
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Ken,
Please see the detail from our developers:
The function ipprResize considers an image as set of cubic pixels. Each pixel is a cube with unit volume (1x1x1). So the function works with center points of pixels. The transformation that maps a source image to the destination one can be expressed by the following formula:
|X'+0.5| |xFactor 0 0 | |X+0.5| |xShift|
|Y'+0.5| = | 0 yFactor 0 | * |Y+0.5| + |yShift|
|Z'+0.5| | 0 0 zFactor| |Z+0.5| |zShift|
Where
(X', Y', Z') – destination point coordinates
(X, Y, Z) – source point coordinates
(xShift, yShift, zShift) – shift values provided by the user
+0.5 is used to get the center of the pixel
Change the formula to get the normalized form
|X'| |xFactor 0 0 | |X| |xShift| |xFactor*0.5 - 0.5|
|Y'| = | 0 yFactor 0 | * |Y| + |yShift| + |yFactor*0.5 - 0.5|
|Z'| | 0 0 zFactor| |Z| |zShift| |zFactor*0.5 - 0.5|
The function ipprWarpAffine considers an image as set of point pixels. Each pixel is a point with zero volume, the distance between neighbor pixels is 1 along each dimension. So the function just works with points. The transformation that maps a source image to the destination one can be expressed by the following formula:
|X'| | A11 A12 A13 | |X| |xShift|
|Y'| = | A21 A22 A23 | * |Y| + |yShift|
|Z'| | A31 A32 A33 | |Z| |zShift|
Where A** matrix of coefficients
And for the scale case, when A11 := xFactor, A22 := yFactor, A33 := zFactor
|X'| |xFactor 0 0 | |X| |xShift|
|Y'| = | 0 yFactor 0 | * |Y| + |yShift|
|Z'| | 0 0 zFactor| |Z| |zShift|
If this is still a issue, could you summit a ticket to our support site: https://www.intel.com/supporttickets? Here are some detail steps:
https://software.intel.com/sites/default/files/managed/97/ce/SubmittingSupportIssue.pdf
Our support team will work with you
Best Regards,
Ying
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ying,
So in ipprResize, the center of integer voxel (x,y,z) has coordinates (x+0.5,y+0.5,z+0.5) but in ipprWarpAffine, the center of integer voxel (x,y,z) has coordinates (x,y,z). That seems to be the essential difference between the 2 methods.
In ipprResize, if dimInZ is the number of input image slices, it would seem to me that ipprGetResizeCuboid calculates the number of output slices as 1 + zFactor(dimInZ-1) so long as zFactor is an integer >= 1.
It would be nice if the documentation was more explicit about these differences.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Ken,
Thank you for the feedback. We will correct the documentation in future releases.
Thanks,
Valentin
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page