mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 09:25:45 +08:00
Merge pull request #23922 from vrabaud:imgwarp
Fix imgwarp at borders when transparent. #23922 I believe this is a proper fix to #23562 The PR #23754 overwrites data while that should not be the case with transparent data. The original test is failing because points at the border do not get computed because they do not have 4 neighbors to be computed. Still ,we can approximate their computation with whatever neighbors that are available. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
parent
85f0074f23
commit
fdfb875208
@ -757,6 +757,37 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (borderType == BORDER_TRANSPARENT) {
|
||||
for (; dx < X1; dx++, D += cn) {
|
||||
if (dx >= dsize.width) continue;
|
||||
const int sx = XY[dx * 2], sy = XY[dx * 2 + 1];
|
||||
// If the mapped point is still within bounds, it did not get computed
|
||||
// because it lacked 4 neighbors. Still, it can be computed with an
|
||||
// approximate formula. If it is outside, the point is left untouched.
|
||||
if (sx >= 0 && sx <= ssize.width - 1 && sy >= 0 && sy <= ssize.height - 1) {
|
||||
const AT* w = wtab + FXY[dx] * 4;
|
||||
WT w_tot = 0;
|
||||
if (sx >= 0 && sy >= 0) w_tot += w[0];
|
||||
if (sy >= 0 && sx < ssize.width - 1) w_tot += w[1];
|
||||
if (sx >= 0 && sy < ssize.height - 1) w_tot += w[2];
|
||||
if (sx < ssize.width - 1 && sy < ssize.height - 1) w_tot += w[3];
|
||||
if (w_tot == 0.f) continue;
|
||||
const WT w_tot_ini = (WT)w[0] + w[1] + w[2] + w[3];
|
||||
const T* S = S0 + sy * sstep + sx * cn;
|
||||
for (int k = 0; k < cn; k++) {
|
||||
WT t0 = 0;
|
||||
if (sx >= 0 && sy >= 0) t0 += S[k] * w[0];
|
||||
if (sy >= 0 && sx < ssize.width - 1) t0 += S[k + cn] * w[1];
|
||||
if (sx >= 0 && sy < ssize.height - 1) t0 += S[sstep + k] * w[2];
|
||||
if (sx < ssize.width - 1 && sy < ssize.height - 1) t0 += S[sstep + k + cn] * w[3];
|
||||
t0 = (WT)(t0 * (float)w_tot_ini / w_tot);
|
||||
D[k] = castOp(t0);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( cn == 1 )
|
||||
for( ; dx < X1; dx++, D++ )
|
||||
{
|
||||
@ -767,12 +798,6 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
|
||||
{
|
||||
D[0] = cval[0];
|
||||
}
|
||||
else if (borderType == BORDER_TRANSPARENT)
|
||||
{
|
||||
if (sx < ssize.width && sx >= 0 &&
|
||||
sy < ssize.height && sy >= 0)
|
||||
D[0] = S0[sy*sstep + sx];
|
||||
}
|
||||
else
|
||||
{
|
||||
int sx0, sx1, sy0, sy1;
|
||||
@ -814,13 +839,6 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
|
||||
for(int k = 0; k < cn; k++ )
|
||||
D[k] = cval[k];
|
||||
}
|
||||
else if (borderType == BORDER_TRANSPARENT)
|
||||
{
|
||||
if (sx < ssize.width && sx >= 0 &&
|
||||
sy < ssize.height && sy >= 0)
|
||||
for(int k = 0; k < cn; k++ )
|
||||
D[k] = S0[sy*sstep + sx*cn + k];
|
||||
}
|
||||
else
|
||||
{
|
||||
int sx0, sx1, sy0, sy1;
|
||||
@ -837,10 +855,6 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
|
||||
v2 = S0 + sy1*sstep + sx0*cn;
|
||||
v3 = S0 + sy1*sstep + sx1*cn;
|
||||
}
|
||||
else if( borderType == BORDER_TRANSPARENT &&
|
||||
((unsigned)sx >= (unsigned)(ssize.width-1) ||
|
||||
(unsigned)sy >= (unsigned)(ssize.height-1)))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
sx0 = borderInterpolate(sx, ssize.width, borderType);
|
||||
|
@ -1672,6 +1672,28 @@ TEST(Imgproc_Remap, issue_23562)
|
||||
remap(src, dst, mapx, mapy, INTER_LINEAR, BORDER_TRANSPARENT);
|
||||
ASSERT_EQ(0.0, cvtest::norm(ref, dst, NORM_INF)) << "channels=" << cn;
|
||||
}
|
||||
|
||||
mapx = Mat1f({3, 3}, {0, 1, 2, 0, 1, 2, 0, 1, 2});
|
||||
mapy = Mat1f({3, 3}, {0, 0, 0, 1, 1, 1, 2, 2, 1.5});
|
||||
for (int cn = 1; cn <= 4; ++cn) {
|
||||
Mat src = cv::Mat(3, 3, CV_32FC(cn));
|
||||
Mat dst = 10 * Mat::ones(3, 3, CV_32FC(cn));
|
||||
for(int y = 0; y < 3; ++y) {
|
||||
for(int x = 0; x < 3; ++x) {
|
||||
for(int k = 0; k < cn; ++k) {
|
||||
src.ptr<float>(y,x)[k] = 10.f * y + x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mat ref = src.clone();
|
||||
for(int k = 0; k < cn; ++k) {
|
||||
ref.ptr<float>(2,2)[k] = (src.ptr<float>(1, 2)[k] + src.ptr<float>(2, 2)[k]) / 2.f;
|
||||
}
|
||||
|
||||
remap(src, dst, mapx, mapy, INTER_LINEAR, BORDER_TRANSPARENT);
|
||||
ASSERT_EQ(0.0, cvtest::norm(ref, dst, NORM_INF)) << "channels=" << cn;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user