Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

bug in WarpAffineQuad

paullumidium_com
Beginner
879 Views

Hi

I think there is a bug in WarpAffineQuad.

If one or more corner of the source quad lies outside the source roi and there is an ippStsAffineQuadChanged error (which seems sensitive enough to occur fairly regularly) then sometimes the destination roi is recalculated causing a one pixel wide strip on the left and/or bottom not to be drawn.

I can work round it ok using GetAffineTransform to calculate the transform and WarpAffineBack to draw it, so this is not critical to me but it would still be nice to have WarpAffineQuad.

Thanks

Paul

0 Kudos
7 Replies
paullumidium_com
Beginner
879 Views

Hi

I'm afraid my workround does not work. I have been running some tests and there seems to be problem with the GetAffineTransform.

If I use two quads with WarpAffineQuad the correct transformation is calculated, but there is the problem of undrawn pixels. BUT if I use the same quads with GetAffineTransform and WarpAffineBack I get quite different results. The problem seems to be in GetAffineTransform mixing geometrical rectangles and roi. The net effect seems to be that all the quad values would need to be adjusted by -0.5 and the roi needs to be 0.5 pixel bigger all round.

If GetAffineTransform took two quads I could at correct for this error but the int values of the srcroi mean I cannot.

I am stuck. If you cannot easily either fix WarpAffineQuad or GetAffineTransform could you let me have the source for GetAffineTransform so that I can patch it?

Thanks

Paul

0 Kudos
Yuri_Tikhomirov__Int
New Contributor I
879 Views

Hi Paul,

Please send us a test case with the problem in ippiWarpAffineQuad function. We will look at it and fix it.

Thanks,

Beg

0 Kudos
paullumidium_com
Beginner
879 Views

Hi Yuri,

That would be great. I have written up a test which shows the first row and column of the destination image failing to be written. Interestingly if the source quad is defined as doubles it works ok but if (as I am doing) they are cast from floats the function fails.

Thanks for your prompt and helpful reply.

Paul

0 Kudos
Yuri_Tikhomirov__Int
New Contributor I
879 Views

Hi Paul,

The function ippiWarpAffineQuad checks correspondence between src and dst quadrangles in the following way:
The function computes transform coefficients, based on the mapping of the source quadrangle to the quadrangle dstQuad.Then it computes the coordinates of the 4th vertex of the destination quadrangle that uniquely depends on the three other vertices. Then the function compares these coordinates with the coordinates specified in dstQuad using the special macro fcmp

#define fcmp(x, y) ((fabs(x) <= 1.e-200) ? (fabs(y) <= 1.e-10) : (fabs(((x) - (y)) / (x)) <= 1.e-10))

If the coordinates are not equal, the function returns the warning message ippStsAffineQuadChanged and continues operation with the computed values. In this case some pixels may be lost. If you use float constants (in your example), the precision is degraded, and srcQuad became not pure parallelogram,
srcQuad[0][0] = 602.795898f;
srcQuad[0][1] = 873.016785f;
srcQuad[1][0] = 1116.818848f;
srcQuad[1][1] = 601.846130f;
srcQuad[2][0] = 964.285339f;
srcQuad[2][1] = 312.708221f;
srcQuad[3][0] = 450.262421f;
srcQuad[3][1] = 583.878906f;
although with double all work correctly.
This function is very sensitive to the precision of the vertices coordinates.

When you use ippiWarpAffineBack, the result will be the same only if the dstQuad is specified as
dstQuad[0][0] = 0;
dstQuad[0][1] = 0;
dstQuad[1][0] = dstWidth - 1;
dstQuad[1][1] = 0;
dstQuad[2][0] = dstWidth - 1;
dstQuad[2][1] = dstHeight - 1;
dstQuad[3][0] = 0;
dstQuad[3][1] = dstHeight - 1;
You can use the function ippiGetAffineTransform, because in this case dstQuad is a rectangle.

Thanks,
Yuri

0 Kudos
paullumidium_com
Beginner
879 Views
Hi Yuri,

I understand that this is happening but if there is a ippStsAffineQuadChanged due to slight imprecision in the shape of the parallelogram then the position of the fourth corner is corrected. There is no reason why this should cause some pixels to be lost in the drawing. The transform should be calculated and the drawing take place in the overlap of the two roi specified.

The calculation of the transform from the two quads ought to have no effect on calculation of the area drawn to as this is defined in the documentation thus:

transform the rectangular ROI of the source image to quadrangle in the destination image;
find the intersection of this quadrangle and the rectangular ROI of the destination image;
update the destination image in the intersection area.

Pixels fully within this intersection after the transform should be drawn to.

It sounds like the very slight correction to the dst quad is also being applied to the dst roi with the effect being magnified by float rounding. There is no reason to adjust the dst roi at all.

This is a bug and still needs fixing.

Also GetAffineTransform is limited in its use as the src area is specified by an int based roi rather than a double based quad. I will check again but I think I am currently getting a 0.5 pixel error in the src which I cannot correct for with int values.

Could you make available a two quad based version of GetAffineTransform?

Thanks

Paul

0 Kudos
paullumidium_com
Beginner
879 Views
Hi Yuri

Do you have an update about this bug?

I have submitted a detailed bug report with supporting test and would hope that you would fix it.

If you are unwilling to fix it could you let me have the source toGetAffineTransform so that I can try and patch it myself?

ALSO
I have another outstanding issue. In ipp 6 you have removed support for resizing using super sampling and square pixels from the library. This this by design or an oversight?
It would be nice to have an answer.
Thanks
Paul
0 Kudos
Yuri_Tikhomirov__Int
New Contributor I
879 Views

Hi Paul,

Idon't think this is a bug, because whenthe function returns the warning ippStsAffineQuadChanged some pixels may be lost.
Please look at the function GetAffineTransformQ calculating transformation matrix for case quad to quad.

void GetAffineTransformQ(const double srcQuad[4][2], const double dstQuad[4][2], double coeffs[2][3])
{
double det, dx1, dx2, dy1, dy2, sx1, sx2, sy1, sy2;
dx1 = dstQuad[1][0] - dstQuad[0][0]; dx2 = dstQuad[2][0] - dstQuad[1][0];
dy1 = dstQuad[1][1] - dstQuad[0][1]; dy2 = dstQuad[2][1] - dstQuad[1][1];
det = 1.0 / (dx1 * dy2 - dx2 * dy1);
sx1 = srcQuad[1][0] - srcQuad[0][0]; sx2 = srcQuad[2][0] - srcQuad[1][0];
sy1 = srcQuad[1][1] - srcQuad[0][1]; sy2 = srcQuad[2][1] - srcQuad[1][1];
coeffs[0][0] = (sx1 * dy2 - sx2 * dy1) * det;
coeffs[0][1] = (sx2 * dx1 - sx1 * dx2) * det;
coeffs[0][2] = srcQuad[2][0] - coeffs[0][0] * dstQuad[2][0] - coeffs[0][1] * dstQuad[2][1];
coeffs[1][0] = (sy1 * dy2 - sy2 * dy1) * det;
coeffs[1][1] = (sy2 * dx1 - sy1 * dx2) * det;
coeffs[1][2] = srcQuad[2][1] - coeffs[1][0] * dstQuad[2][0] - coeffs[1][1] * dstQuad[2][1];
}

About your second question...
The function ippiResizeSqrPixel support Super Sampling method for shrinking images.
It was a misprint in the documentation.
Please set interpolation parameter as IPPI_INTER_SUPER

Thanks,
Yuri

0 Kudos
Reply