- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Paul,
Please send us a test case with the problem in ippiWarpAffineQuad function. We will look at it and fix it.
Thanks,
Beg
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page