Open nh2 opened 4 years ago
In a previous short segfault investigation, I made myself the following note, which might be helpful:
With this diff
diff --git a/libs/tex/poisson_blending.cpp b/libs/tex/poisson_blending.cpp
index 2bed1da..b0eed1e 100644
--- a/libs/tex/poisson_blending.cpp
+++ b/libs/tex/poisson_blending.cpp
@@ -34,12 +34,19 @@ bool valid_mask(mve::ByteImage::ConstPtr mask){
const int height = mask->height();
for (int x = 0; x < width; ++x)
- if (mask->at(x, 0, 0) == 255 || mask->at(x, height - 1, 0) == 255)
+ if (mask->at(x, 0, 0) == 255 || mask->at(x, height - 1, 0) == 255) {
+ std::cerr << "valid_mask x failed at x=" << x << ", height=" << height << ", "
+ << "mask->at(" << x << ", 0, 0) = " << (unsigned int) mask->at(x, 0, 0) << ", "
+ << "mask->at(" << x << ", " << (height - 1) << ", 0) = " << (unsigned int) mask->at(x, height - 1, 0)
+ << std::endl;
return false;
+ }
for (int y = 0; y < height; ++y)
- if (mask->at(0, y, 0) == 255 || mask->at(width - 1, y, 0) == 255)
+ if (mask->at(0, y, 0) == 255 || mask->at(width - 1, y, 0) == 255) {
+ std::cerr << "valid_mask y failed" << std::endl;
return false;
+ }
//TODO check for sane boundary conditions...
I get:
valid_mask x failed at x=1, height=3, mask->at(1, 0, 0) = 64, mask->at(1, 2, 0) = 255
Mask check failed
Perhaps the 64
comes from here? https://github.com/nmoehrle/mvs-texturing/blob/3840a53de3a21c955571b6214f5b4721e11d4a97/libs/tex/texture_patch.cpp#L99
Using this script with gdb
to print the mask
in my case:
print mask->width()
print mask->height()
set $y = 0
while ($y < mask->height())
set $x = 0
while ($x < mask->width())
print { (int) $x, (int) $y, 0, (int) mask->at($x, $y, 0) }
set $x=$x+1
end
set $y=$y+1
print ""
end
prints
(gdb) print mask->width()
$510 = 3
(gdb) print mask->height()
$511 = 3
(gdb) set $y = 0
(gdb) while ($y < mask->height())
> set $x = 0
> while ($x < mask->width())
> print { (int) $x, (int) $y, 0, (int) mask->at($x, $y, 0) }
> set $x=$x+1
> end
> set $y=$y+1
> print ""
>end
$512 = {0, 0, 0, 64}
$513 = {1, 0, 0, 64}
$514 = {2, 0, 0, 64}
$515 = ""
$516 = {0, 1, 0, 64}
$517 = {1, 1, 0, 255}
$518 = {2, 1, 0, 255}
$519 = ""
$520 = {0, 2, 0, 64}
$521 = {1, 2, 0, 255}
$522 = {2, 2, 0, 64}
$523 = ""
So that 3x3 mask looks like:
64 64 64
64 255 255
64 255 64
And valid_mask
forbids the bottom middle 255 in this case.
How comes it's there?
In a previous short segfault investigation
Just for clarification, I have confirmed that also in this new case it is the valid_mask
assertion failure:
Blending texture patches 100%...valid_mask x failed at x=1, height=3, mask->at(1, 0, 0) = 64, mask->at(1, 2, 0) = 255
texrecon: /root/mvs-texturing/mvs-texturing-7126bb3/libs/tex/poisson_blending.cpp:64: void poisson_blend(mve::Image<float>::ConstPtr, mve::Image<unsigned char>::ConstPtr, mve::Image<float>::Ptr, float): Assertion `valid_mask(mask)' failed.
and that with assertions enabled the valgrind memory access errors disappear; so it's most likely just the assertion failure that needs to be investigated here.
Some insight:
I inserted after this line https://github.com/nmoehrle/mvs-texturing/blob/3840a53de3a21c955571b6214f5b4721e11d4a97/libs/tex/texture_patch.cpp#L72
assert(x != get_width() - 1 && y != get_height() - 1);
which triggered as well.
Again using gdb
, I printed:
$1 = 0
(gdb) p min_y
$2 = 0
(gdb) p max_x
$3 = 3
(gdb)
$4 = 3
(gdb) p max_y
$5 = 3
(gdb) p bcoords
$6 = {v = {1, -0, 0}}
(gdb) p x
$7 = 2
(gdb) p y
$8 = 1
(gdb) p bcoords.minimum()
$9 = -0
(gdb) p tri
$10 = {v1 = {v = {2, 1}}, v2 = {v = {1, 1}}, v3 = {v = {1, 2}}, detT = -1, aabb = {min_x = 1, min_y = 1, max_x = 2, max_y = 2}}
(gdb) p v1
$11 = {v = {2, 1}}
(gdb) p v2
$12 = {v = {1, 1}}
(gdb) p v3
$13 = {v = {1, 2}}
So we have the Tri
triangle {2,1}, {1,1}, {1, 2}
and it computes that the coords {1, 2}
are inside = true
.
So mask[1][2]
gets set to 255
, and in general this triangle gets rendered as
64 64 64
64 255 255
64 255 64
as shown above (you can see the triangle being rendered in the mask as 255s; they form a triangle).
So clearly the border area is not free of 255
, as demanded by the later code.
Should it be? Should the triangle be rendered only as the pixel in the middle being 255? Also what ensures that the triangle tri
doesn't have a point at {0, 0}
?
Also interesting but probably not related to the problem: When for the Tri
triangle {2,1}, {1,1}, {1, 2}
it computes that the barycentric coords of {1, 2}
in this triangle (should be {1, -0, 0}
) are {1, -0, 0}
-- negative floating point zero!
This works out OK because in the check https://github.com/nmoehrle/mvs-texturing/blob/3840a53de3a21c955571b6214f5b4721e11d4a97/libs/tex/texture_patch.cpp#L70
bool inside = bcoords.minimum() >= 0.0f;
- {1, -0, 0}.minimum()
will be -0.0f
which is still >= 0.0f
.
But I wonder whether it's intended that get_barycentric_coords()
returns negative zeros.
For my reference, the place where the patches are generated is https://github.com/nmoehrle/mvs-texturing/blob/7126bb3aa34a4a9a36003efa06a1db5fe07509fd/libs/tex/generate_texture_patches.cpp#L114-L118; that's where the texture_patch_border = 1
is also considered (the only other place is here).
I've made a PR that fixes it, with full explanation, at #126.
Thank you very much for the detailed analysis and fix! I cannot look at it at the moment but will do so within the next days.
With the versions from https://github.com/nmoehrle/mvs-texturing/issues/120#issuecomment-541404178, I sometimes (nondeterministically, see also #124) get segfault, and
valgrind
reportsInvalid read of size 4
: