Affine transform produces invalid outputs

Affine transform produces invalid outputs

Hi,

I am trying to implement this simple test program in IPP. It enlarges a sample 2d matrix by 200%. This is the Matlab version:

A = uint8([1 2 3; 4 5 6]) % Input matrix

tform = affine2d([2 0 0; 0 2 0; 0 0 1]); % Define transform

B = imwarp(A, tform, 'nearest') % Run the transform

I get this output, as expected:

A =

    1    2    3
    4    5    6

B =

    1    1    2    2    3    3
    1    1    2    2    3    3
    4    4    5    5    6    6
    4    4    5    5    6    6

This is IPP equivalent code:

// ipptest.cpp : Attempt to use WarpAffine to scale an image 200%.
//

#include "ipp.h"

#include <iostream>
#include <iomanip>

typedef unsigned char byte;

int main(int argc, char* argv[])
{
 ippInit();

 // Source image and ROI
 static const int kHEIGHT = 2;
 static const int kWIDTH = 3;
 byte srcImage[kHEIGHT][kWIDTH] =
 {
  { 1, 2, 3 },
  { 4, 5, 6 }
 };

 IppiRect srcRoi;
 srcRoi.x = srcRoi.y = 0;
 srcRoi.width = kWIDTH + 1;
 srcRoi.height = kHEIGHT + 1;

 IppiSize srcSize;
 srcSize.height = kHEIGHT;
 srcSize.width = kWIDTH;


 // Destinatino image buffer and ROI
 byte destImage[kHEIGHT * 2][kWIDTH * 2];

 IppiRect destRoi;
 destRoi.x = destRoi.y = 0;
 destRoi.width = kWIDTH * 2 + 1;
 destRoi.height = kHEIGHT * 2 + 1;


 // Scale source image by 200% in both x and y
 double coeffs[2][3] =
 {
  { 2.0, 0.0, 0.0 },
  { 0.0, 2.0, 0.0 }
 };

 IppStatus stat;
 double bound[2][2];

 // Following code is from AffineTransform sample to figure out destination width and height
 stat = ippiGetAffineBound(srcRoi, bound, coeffs);
 double width = bound[1][0] - bound[0][0];
 double height = bound[1][1] - bound[0][1];

 std::cout << "IPP sample says " << kWIDTH << " x " << kHEIGHT << " image should be scaled 200% to " << width << " x " << height << std::endl;

 // Print input image
 std::cout << std::endl << "Source image: " << std::endl;
 for (int row = 0; row < kHEIGHT; ++row)
 {
  for (int col = 0; col < kWIDTH; ++col)
  {
   std::cout << " " << (unsigned int)srcImage[row][col];
  }
  std::cout << std::endl;
 }

 // Apply transform
 stat = ippiWarpAffine_8u_C1R(
  (const Ipp8u*)srcImage, srcSize, kWIDTH, srcRoi,
  (Ipp8u*)destImage, kWIDTH * 2, destRoi,
  coeffs, IPPI_INTER_NN);

 // Print output image
 std::cout << std::endl << "Transformed image: " << std::endl;
 for (int row = 0; row < kHEIGHT * 2; ++row)
 {
  for (int col = 0; col < kWIDTH * 2; ++col)
  {
   std::cout << " " << (unsigned int)destImage[row][col];
  }
  std::cout << std::endl;
 }

 return 0;
}

But what I get is this:

IPP sample says 3 x 2 image should be scaled 200% to 6 x 4

Source image:
 1 2 3
 4 5 6

Transformed image:
 1 2 2 3 3 204
 4 5 5 6 6 204
 4 5 5 6 6 204
 204 204 204 204 204 204
Press any key to continue . . .

Obviously the transformed image isn't correct. Can somebody point out what's wrong, please.

 

 

 

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi Goran,

Which version of Matlab is used?

To check the transformation I implemented the following small test for Matlab.

A = uint8([1 2 3; 4 5 6]) % Input matrix
tform=maketform('affine',[2 0 0; 0 2 0; 0 0 1]); % Define transform
B = imtransform(A, tform, 'nearest') % Run the transform

I got this result:

A =

    1    2    3
    4    5    6

B =

    1    2    2    3    3
    4    5    5    6    6
    4    5    5    6    6

Regards, Valentin

OK, I see, I get the same output when I run your version, so Matlab and IPP match.

But could you please explain why if I have a 2x3 matrix and enlarge it by 200% I get 3x5 output instead of 4x6.

Wouldn't it make sense that using [2 0; 0 2] linear transform matrix would double the size of the input matrix?

Thanks!

Thank you for the question. The matrix represents the image, where each pixel is a point that has own color value and (x,y) coordinates. Pixel coordinates correspond to the position of the number in the matrix. So if we have MxN matrix then the left-top point has coordinates (0,0) and the right-bottom point has coordinates (N-1,M-1). When we double increase the matrix size, we obtain a new matrix with the left-top point (0,0) and the right-bottom point ( (N-1) * 2, (M-1) * 2 ). In case of 2x3 matrix the right-bottom point has coordinates (x,y) = ( (3 - 1)*2 , (2 - 1)*2 ) = (4, 2), therefore the size of the enlarged matrix is 3x5.

Regards, Valentin

Thanks for the explanation!

Leave a Comment

Please sign in to add a comment. Not a member? Join today