-
-
Notifications
You must be signed in to change notification settings - Fork 827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mesh] Texturing: Multi-band blending #629
Conversation
Use an Image class instead of vector<Color> and width, height.
Does not change the results yet, but start to use the multiband.
Calculate the laplacian pyramid of an image with successives downscales (instead of successives blurs) -> memory saving
valid operators =, [] & resize without copying elements
calculate difference between an image of size s and an other of size s/2
For each camera, calculate the corresponding laplacian pyramid. For each texture triangle, fuse the contributions of frequencies bands from the best scoring cameras
save all frequency bands for all textures
Let openImageIO choose the size of the convolution kernel when downscaling by two & replace maxNbImagesForFusion by multiBandNbContrib
Create the texture padding with only two passes of the image instead of 2*padding
Add param to control the level of blur between each level of the laplacian pyramid (previously fixed to 2)
Add number of bands param, to control the number of level of the laplacian pyramid
Refine calculus of the number of atlases simultaneously computable
Texture padding computed in 2 passes instead of padding*2 passes
Triangles contribute to atlas textures according to their score (ie. the area of reprojection on the camera) -> less artefacts, especially on low frequencies band
Create new file to test multi-band blending on one image
Add colorspace attribute to ImagesCache and read images in that colorspace (LINEAR for depthMap, SRGB for texturing)
New colorspace type (AUTO_FROM_SRGB) -> calculate texture atlases in sRGB for multi-band blending accuracy
readImage kept to much space in memory
Bool to choose to use scores + scores in float type + simple rename
texParams.multibandNbContrib holds contributions to each frequency band, not the sum of contributions to all higher frequency bands as before
Delete MultiBandBlending class & calculate laplacian pyramid directly in the image class. Delete useless functions and add comments [mvsData] Image: some cleaning + split into .hpp / .cpp Create a .cpp file to write the implementation of elaborate functions
Simplify imageIO management in MVS by having only one imageIO file. Override imageIO methods to take directly mvsData::Image class in argument (instead of width, height and buffer)
Simplify image management by having only one image class. [mvsData] Image: refactoring & add simple methods [mesh] Texturing: use Image class for AccuImage structure (instead of vector<Color>) + use imageIO methods taking an Image in argument [mvsUtils] fileIO: adapt the method for loading images to use mvsData::Image
src/aliceVision/mesh/Texturing.cpp
Outdated
@@ -451,7 +451,7 @@ void Texturing::generateTexturesSubSet(const mvsUtils::MultiViewParams& mp, | |||
if(contrib + 1 == nbContribLevel) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simpler and avoid to access outside of the array.
if(contrib + 1 == texParams.multiBandNbContrib[band])
{
++band;
}
So we could remove the variable nbContribLevel
.
@@ -451,7 +451,7 @@ void Texturing::generateTexturesSubSet(const mvsUtils::MultiViewParams& mp, | |||
if(contrib + 1 == nbContribLevel) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few lines above, we have:
int nbContribMax = std::min(texParams.multiBandNbContrib.back(), static_cast<int>(scorePerCamId.size()));
I think yes, but just to be sure: Does texParams.multiBandNbContrib
still contains cumulative values in the latest version?
src/aliceVision/mesh/Texturing.cpp
Outdated
@@ -259,17 +259,22 @@ void Texturing::generateTextures(const mvsUtils::MultiViewParams &mp, | |||
const boost::filesystem::path &outPath, EImageFileType textureFileType) | |||
{ | |||
ALICEVISION_LOG_INFO("Texturing: Use multiband blending with the following contributions per band:"); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{
// Ensure that contribution levels do not contain 0 and are sorted (as they represent cumulative values).
auto& m = texParams.multiBandNbContrib;
m.erase(std::remove(std::begin(m), std::end(m), 0), std::end(m));
texParams.nbBand = m.size();
if(!std::is_sorted(std::begin(m), std::end(m)))
{
ALICEVISION_LOG_INFO("Sorting contributions per band (necessary).");
std::sort(std::begin(m), std::end(m));
}
}
src/samples/CMakeLists.txt
Outdated
@@ -10,7 +10,6 @@ add_subdirectory(featuresRepeatability) | |||
# add_subdirectory(imageData) | |||
add_subdirectory(imageDescriberMatches) | |||
add_subdirectory(kvldFilter) | |||
add_subdirectory(multiBandBlending) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a mistake as the sample itself is not removed...
@@ -38,7 +38,6 @@ endif() | |||
# MVS modules | |||
|
|||
if(ALICEVISION_BUILD_MVS) | |||
add_subdirectory(imageIO) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We tried to keep a split between IO and data structures as almost all modules have dependencies to data structures.
So if we don't split it, all modules will have dependencies to IO.
But maybe this commit is a needed intermediate solution before a new change? If not, we do not want to merge mvsData and imageIO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a several files related to image IO:
- image/io.hpp
// SfM: functions to read/writes images
- imageIO/image.hpp
// MVS: functions to read/write images, relies on mvsData for data structure types (rgb, Color and now Image)
- mvsData/imageIO.hpp (image.hpp on develop)
// MVS: containing EImageFileType enum
The idea was to start simplifying things. We will probably want to merge image types and IO at some point, but it already seems weird to have, for the MVS part, this split between imageIO/image.hpp
and mvsData/imageIO.hpp
. And everything that uses mvsData also uses imageIO, so the merge does not seem that problematic IMHO. But if we want to keep this imageIO
module as the one that will stay, maybe it could be the other way around: move what's inside mvsData/imageIO.hpp into the imageIO module.
src/aliceVision/mesh/Texturing.cpp
Outdated
//conversion ImagesCache::Img -> Image | ||
mvsUtils::ImagesCache::ImgPtr imgPtr = imageCache.getImg_sync(camId); | ||
Image camImg(imgPtr->data, imgPtr->getWidth(), imgPtr->getHeight()); | ||
const Image& camImg = *(imageCache.getImg_sync(camId)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getImg_sync
returns an ImgPtr
which is a std::shared_ptr<Img>
.
If you remove the temporary variable and directly get the value from the shared_ptr, the shared_ptr ownership is removed.
@@ -152,24 +152,24 @@ struct Texturing | |||
// Create buffer for the set of output textures | |||
struct AccuImage | |||
{ | |||
std::vector<Color> img; | |||
Image img; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -21,48 +22,11 @@ namespace mvsUtils { | |||
|
|||
class ImagesCache | |||
{ | |||
public: | |||
class Img |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
const camera::IntrinsicBase* intrinsicPtr = _sfmData.getIntrinsicPtr(view.getIntrinsicId()); | ||
|
||
Vec2 pix_disto = intrinsicPtr->get_d_pixel({pixRC.x, pixRC.y}); | ||
return isPixelInImage(Pixel(pix_disto.x(), pix_disto.y()), camId, margin); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the MVS structures have a global downscale (backed in all matrices, etc.) but it's not the case for the sfmData which contains the original SfM.
So we need to compensate for that:
const double s = getDownscaleFactor(camId);
const Vec2 pix_disto = intrinsicPtr->get_d_pixel({pixRC.x * s, pixRC.y * s}) / s;
src/aliceVision/mesh/Texturing.cpp
Outdated
imageCache.refreshData(camId); | ||
const Image& camImg = *(imageCache.getImg_sync(camId)); | ||
imageCache.refreshData(camId); | ||
mvsUtils::ImagesCache::ImgPtr imgPtr = imageCache.getImg_sync(camId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mvsUtils::ImagesCache::ImgPtr imgPtr = imageCache.getImg_sync(camId); // keep ownership
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to rename ImgPtr
into ImgSharedPtr
.
When texturing: check if mesh triangles reproject into both source and undisto images. [mvsUtils] MultiViewParams: new method to project a triangle into source image (= image with distortion) [mesh] Mesh: adapt triangle reprojection functions
Update nbContribMax (= max number of contribution for a camera): number of contributions used to be cumulative but not anymore (more practical for the user)
Incorrect use of shared_ptr: if you remove the temporary variable and directly get the value from the shared_ptr, the shared_ptr ownership is removed.
code cleaning + setting multiBandDownscale default value to 4 + renaming ImagesCache::ImgPtr to ImagesCache::ImgSharedPtr
only keep triangles with sufficient reprojection area
846158b
to
7fdc82b
Compare
src/aliceVision/mvsData/imageIO.hpp
Outdated
else | ||
to = to_; | ||
} | ||
OutputFileColorSpace() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
= default;
src/aliceVision/mvsData/imageIO.cpp
Outdated
@@ -294,29 +379,34 @@ void writeImage(const std::string& path, | |||
fs::rename(tmpPath, path); | |||
} | |||
|
|||
void writeImage(const std::string& path, int width, int height, const std::vector<unsigned char>& buffer, EImageQuality imageQuality, EImageColorSpace imageColorSpace, const oiio::ParamValueList& metadata) | |||
void writeImage(const std::string& path, int width, int height, const std::vector<unsigned char>& buffer, EImageQuality imageQuality, OutputFileColorSpace colorspace, const oiio::ParamValueList& metadata) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const OutputFileColorSpace& colorspace
@@ -238,7 +323,7 @@ void writeImage(const std::string& path, | |||
int nchannels, | |||
const std::vector<T>& buffer, | |||
EImageQuality imageQuality, | |||
EImageColorSpace imageColorSpace, | |||
OutputFileColorSpace colorspace, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const OutputFileColorSpace& colorspace
src/aliceVision/mvsData/imageIO.hpp
Outdated
|
||
struct OutputFileColorSpace | ||
{ | ||
EImageColorSpace from = EImageColorSpace::LINEAR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EImageColorSpace from{EImageColorSpace::LINEAR};
EImageColorSpace to{EImageColorSpace::AUTO};
mapIdCamId.resize( N_PRELOADED_IMAGES, -1 ); | ||
mapIdClock.resize( N_PRELOADED_IMAGES, clock() ); | ||
} | ||
|
||
ImagesCache::~ImagesCache() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
= default
LGTM! |
Description
Largely improve the texturing quality by using multi-band blending technique.
Split each input camera into frequency bands, by calculating its laplacian pyramid. For each output texture file, it computes the texture fusion per frequency bands with different number of contributions. The color averaging is now weighted by a score defined by the triangle reprojection area.
The textures per frequency bands are then combined to create the final output texture files.
Features list
Implementation remarks
Fix #644