1

I am working on a function in a class to store images. The purpose of this function is the perform linear transformations using a 2D matrix (I don't plan on supporting translation). The way I wanted to do it was to test transform the coordinates of the corners of the original image and use the extreme values to calculate the necessary size for the resulting transformed image.

One I have the new image I wanted to loop over all the pixels in the new image and use the inverse transform the calculate where on the original image the new pixels should get their color from (using bilinear interpolation).

I started writing the following function. It does not yet do anything to the image. The issue is that when I pass a set of coordinates through the transform function and then pass those new coordinates through the inverse function I expect to get the original values back. However I am not getting back the original values.

Image Image::matrix_transform(float m11, float m12, float m21, float m22) const
{
    float det = m11 * m22 - m12 * m21;
    img_assert(det, "Matrix not invertible.");

    //inverse matrix values
    float im11 = m22 / det;
    float im22 = m11 / det;
    float im21 = -m21 / det;
    float im12 = -m12 / det;

    //transformation 
    const auto t = [m11, m12, m21, m22](float& x, float& y)
    {
        x = x * m11 + y * m12;
        y = x * m21 + y * m22;
    };

    //inverse
    const auto ti = [im11, im12, im21, im22](float& x, float& y)
    {
        x = x * im11 + y * im12;
        y = x * im21 + y * im22;
    };

    float x00 = 0.0f, y00 = 0.0f;
    float x11 = w, y11 = h;
    float x10 = 0.0f, y10 = h;
    float x01 = w, y01 = 0.0f;

    std::cout << x00 << " " << y00 << std::endl;
    std::cout << x01 << " " << y01 << std::endl;
    std::cout << x10 << " " << y10 << std::endl;
    std::cout << x11 << " " << y11 << std::endl;

    t(x00, y00);
    t(x11, y11);
    t(x10, y10);
    t(x01, y01);

    ti(x00, y00);
    ti(x11, y11);
    ti(x10, y10);
    ti(x01, y01);

    std::cout << x00 << " " << y00 << std::endl;
    std::cout << x01 << " " << y01 << std::endl;
    std::cout << x10 << " " << y10 << std::endl;
    std::cout << x11 << " " << y11 << std::endl;

    return *this;
}

Here is how I am calling the function (a simple rotation matrix).

img.matrix_transform(cos(angle), -sin(angle), sin(angle), cos(angle));

Here is the output I get...

0 0
2500 0
0 1655
2500 1655


0 0
1975.95 -722.386
-743.978 629.455
1231.97 -92.9314

I was expecting the top set of coordinates to match the bottom.

1 Answer 1

2

Here

    x = x * m11 + y * m12;
    y = x * m21 + y * m22;

the second assignment uses the already modified x value. Change it to

    auto newx = x * m11 + y * m12;
    y = x * m21 + y * m22;
    x = newx;
1
  • Thanks. That was so simple but caused me an hour of confusion.
    – chasep255
    Commented Oct 19, 2015 at 15:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.