Browse Source

GPU并行优化

master
hesuicong 2 months ago
parent
commit
a395698345
  1. 3
      apps/TextureMesh/TextureMesh.cpp
  2. 41
      libs/MVS/CMakeLists.txt
  3. 77
      libs/MVS/SceneTexture.cpp

3
apps/TextureMesh/TextureMesh.cpp

@ -1049,6 +1049,7 @@ bool checkFileExistence(const std::string& filename) {
int main(int argc, LPCTSTR* argv) int main(int argc, LPCTSTR* argv)
{ {
TD_TIMER_START();
#ifdef _DEBUGINFO #ifdef _DEBUGINFO
// set _crtBreakAlloc index to stop in <dbgheap.c> at allocation // set _crtBreakAlloc index to stop in <dbgheap.c> at allocation
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// | _CRTDBG_CHECK_ALWAYS_DF); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// | _CRTDBG_CHECK_ALWAYS_DF);
@ -1128,7 +1129,6 @@ int main(int argc, LPCTSTR* argv)
printf("MAKE_PATH_SAFE(OPT::strViewsFileName): %s\n", MAKE_PATH_SAFE(OPT::strViewsFileName).c_str()); printf("MAKE_PATH_SAFE(OPT::strViewsFileName): %s\n", MAKE_PATH_SAFE(OPT::strViewsFileName).c_str());
if (!OPT::strViewsFileName.empty()) if (!OPT::strViewsFileName.empty())
views = ParseViewsFile(MAKE_PATH_SAFE(OPT::strViewsFileName), scene); views = ParseViewsFile(MAKE_PATH_SAFE(OPT::strViewsFileName), scene);
printf("Second\n");
// compute mesh texture // compute mesh texture
TD_TIMER_START(); TD_TIMER_START();
if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::minCommonCameras, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness, if (!scene.TextureMesh(OPT::nResolutionLevel, OPT::nMinResolution, OPT::minCommonCameras, OPT::fOutlierThreshold, OPT::fRatioDataSmoothness,
@ -1164,6 +1164,7 @@ int main(int argc, LPCTSTR* argv)
sml.Save(baseFileName+_T("_orthomap.txt")); sml.Save(baseFileName+_T("_orthomap.txt"));
} }
VERBOSE("All TextureMesh completed (%s)!", TD_TIMER_GET_FMT().c_str());
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/

41
libs/MVS/CMakeLists.txt

@ -12,6 +12,37 @@ if(VCG_FOUND)
add_definitions(${VCG_DEFINITIONS}) add_definitions(${VCG_DEFINITIONS})
endif() endif()
# 在find_package(CUDA)PIC
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(CUDA REQUIRED)
SET(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}
-Xcompiler=-fPIC
--relocatable-device-code=true
--ptxas-options=-v
-gencode arch=compute_75,code=sm_75
")
# CUDACMake
IF(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
ENABLE_LANGUAGE(CUDA)
ENDIF()
cuda_add_library(MeshTextureCUDA
cuda/MeshTextureCUDA.cu
)
SET_TARGET_PROPERTIES(MeshTextureCUDA PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON #
POSITION_INDEPENDENT_CODE ON
)
# CUDA
TARGET_COMPILE_OPTIONS(MeshTextureCUDA PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-fPIC>
)
set(CERES_LIBS "") set(CERES_LIBS "")
if(OpenMVS_USE_CERES) if(OpenMVS_USE_CERES)
FIND_PACKAGE(Ceres) FIND_PACKAGE(Ceres)
@ -44,11 +75,19 @@ IF(CMAKE_VERSION VERSION_GREATER_EQUAL 3.16.0)
TARGET_PRECOMPILE_HEADERS(MVS PRIVATE "Common.h") TARGET_PRECOMPILE_HEADERS(MVS PRIVATE "Common.h")
endif() endif()
TARGET_LINK_LIBRARIES(MeshTextureCUDA
${CUDA_LIBRARIES}
${OpenCV_LIBRARIES}
cudart_static
)
# Link its dependencies # Link its dependencies
if(_USE_CUDA) if(_USE_CUDA)
SET_TARGET_PROPERTIES(MVS PROPERTIES CUDA_ARCHITECTURES "50;72;75") SET_TARGET_PROPERTIES(MVS PROPERTIES CUDA_ARCHITECTURES "50;72;75")
endif() endif()
TARGET_LINK_LIBRARIES(MVS PRIVATE Common Math IO CGAL::CGAL ${CERES_LIBRARIES} ${CUDA_CUDA_LIBRARY}) TARGET_LINK_LIBRARIES(MVS PRIVATE Common Math IO CGAL::CGAL ${CERES_LIBRARIES} ${CUDA_CUDA_LIBRARY}
MeshTextureCUDA
${CUDA_LIBRARIES})
if(OpenMVS_USE_PYTHON) if(OpenMVS_USE_PYTHON)
# Create the Python wrapper # Create the Python wrapper

77
libs/MVS/SceneTexture.cpp

@ -40,6 +40,7 @@
#include <pybind11/embed.h> #include <pybind11/embed.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include "ConfigEnv.h" #include "ConfigEnv.h"
#include "cuda/MeshTextureCUDA.h"
namespace py = pybind11; namespace py = pybind11;
@ -73,6 +74,7 @@ using namespace MVS;
#define MASK_FACE_OCCLUSION #define MASK_FACE_OCCLUSION
// #define DISPLAY_DEMO // #define DISPLAY_DEMO
#define CACHE_MASK #define CACHE_MASK
#define USE_CUDA
// inference algorithm // inference algorithm
#if TEXOPT_INFERENCE == TEXOPT_INFERENCE_LBP #if TEXOPT_INFERENCE == TEXOPT_INFERENCE_LBP
@ -6078,7 +6080,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
LabelArr labels; LabelArr labels;
// 为每个面片单独决定是否使用虚拟面算法 // 为每个面片单独决定是否使用虚拟面算法
Mesh::FaceIdxArr virtualFacesI; // 使用虚拟面算法的面片 // Mesh::FaceIdxArr virtualFacesI; // 使用虚拟面算法的面片
Mesh::FaceIdxArr perFaceFaces; // 使用逐面算法的面片 Mesh::FaceIdxArr perFaceFaces; // 使用逐面算法的面片
/* /*
@ -6104,12 +6106,9 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
// construct and use virtual faces for patch creation instead of actual mesh faces; // construct and use virtual faces for patch creation instead of actual mesh faces;
// the virtual faces are composed of coplanar triangles sharing same views // the virtual faces are composed of coplanar triangles sharing same views
if (bUseVirtualFaces) { if (bUseVirtualFaces) {
Mesh::FaceIdxArr mapFaceToVirtualFace(faces.size()); // for each mesh face ID, store the virtual face ID witch contains it Mesh::FaceIdxArr mapFaceToVirtualFace(faces.size()); // for each mesh face ID, store the virtual face ID witch contains it
// 标记使用虚拟面算法的面片 // 标记使用虚拟面算法的面片
std::vector<bool> isVirtualFace(faces.size(), true); std::vector<bool> isVirtualFace(faces.size(), true);
// 1) create FaceToVirtualFaceMap // 1) create FaceToVirtualFaceMap
FaceDataViewArr virtualFacesDatas; FaceDataViewArr virtualFacesDatas;
VirtualFaceIdxsArr virtualFaces; // stores each virtual face as an array of mesh face ID VirtualFaceIdxsArr virtualFaces; // stores each virtual face as an array of mesh face ID
@ -6117,7 +6116,9 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
// CreateVirtualFaces3(facesDatas, virtualFacesDatas, virtualFaces, minCommonCameras); // CreateVirtualFaces3(facesDatas, virtualFacesDatas, virtualFaces, minCommonCameras);
// CreateVirtualFaces4(facesDatas, virtualFacesDatas, virtualFaces, mapFaceToVirtualFace, minCommonCameras); // CreateVirtualFaces4(facesDatas, virtualFacesDatas, virtualFaces, mapFaceToVirtualFace, minCommonCameras);
// CreateVirtualFaces6(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras); // CreateVirtualFaces6(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
TD_TIMER_STARTD();
CreateVirtualFaces7(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras); CreateVirtualFaces7(facesDatas, virtualFacesDatas, virtualFaces, isVirtualFace, minCommonCameras);
DEBUG_EXTRA("CreateVirtualFaces7 completed: %s", TD_TIMER_GET_FMT().c_str());
size_t controlCounter(0); size_t controlCounter(0);
FOREACH(idxVF, virtualFaces) { FOREACH(idxVF, virtualFaces) {
@ -6137,7 +6138,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
} }
} }
printf("perFaceFaces.size = %d\n", perFaceFaces.size()); // printf("perFaceFaces.size = %d\n", perFaceFaces.size());
ASSERT(controlCounter == faces.size()); ASSERT(controlCounter == faces.size());
// 2) create function to find virtual faces neighbors // 2) create function to find virtual faces neighbors
@ -8154,7 +8155,20 @@ void MeshTexture::LocalSeamLeveling3()
// extract image // extract image
const Image8U3& image0(images[texturePatch.label].image); const Image8U3& image0(images[texturePatch.label].image);
Image32F3 image, imageOrg; Image32F3 image, imageOrg;
#ifdef USE_CUDA
if (MeshTextureCUDA::ConvertToCUDA(image0(texturePatch.rect), image, 1.0/255.0))
{
// printf("ConvertToCUDA Successed!\n");
}
else
{
image0(texturePatch.rect).convertTo(image, CV_32FC3, 1.0/255.0);
// printf("ConvertToCUDA Failed!\n");
}
#else
image0(texturePatch.rect).convertTo(image, CV_32FC3, 1.0/255.0); image0(texturePatch.rect).convertTo(image, CV_32FC3, 1.0/255.0);
#endif
image.copyTo(imageOrg); image.copyTo(imageOrg);
// render patch coverage // render patch coverage
Image8U mask(image.size()); { Image8U mask(image.size()); {
@ -8252,11 +8266,43 @@ void MeshTexture::LocalSeamLeveling3()
} }
// make sure the border is continuous and // make sure the border is continuous and
// keep only the exterior tripe of the given size // keep only the exterior tripe of the given size
#ifdef USE_CUDA
if (MeshTextureCUDA::ProcessMaskCUDA(mask, 20))
{
// printf("Success ProcessMaskCUDA!\n");
// 成功使用CUDA加速
}
else
{
// 回退到CPU版本
// printf("Failed ProcessMaskCUDA!\n");
ProcessMask(mask, 20);
}
#else
ProcessMask(mask, 20); ProcessMask(mask, 20);
#endif
// compute texture patch blending // compute texture patch blending
#ifdef USE_CUDA
if (MeshTextureCUDA::PoissonBlendCUDA(image, imageOrg, mask, 1.0f))
{
// printf("Success PoissonBlendCUDA!");
// 成功使用CUDA加速
}
else
{
// 回退到CPU版本
// printf("Failed PoissonBlendCUDA!");
PoissonBlending(imageOrg, image, mask, 1.0f);
}
#else
PoissonBlending(imageOrg, image, mask); PoissonBlending(imageOrg, image, mask);
#endif
// apply color correction to the patch image // apply color correction to the patch image
cv::Mat imagePatch(image0(texturePatch.rect)); cv::Mat imagePatch(image0(texturePatch.rect));
#ifdef TEXOPT_USE_OPENMP
#pragma omp parallel for collapse(2)
#endif
for (int r=0; r<image.rows; ++r) { for (int r=0; r<image.rows; ++r) {
for (int c=0; c<image.cols; ++c) { for (int c=0; c<image.cols; ++c) {
if (mask(r,c) == empty) if (mask(r,c) == empty)
@ -8372,6 +8418,8 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel
LOG_OUT() << "First loop completed" << std::endl; LOG_OUT() << "First loop completed" << std::endl;
TD_TIMER_STARTD();
// perform seam leveling // perform seam leveling
if (texturePatches.size() > 2 && (bGlobalSeamLeveling || bLocalSeamLeveling)) { if (texturePatches.size() > 2 && (bGlobalSeamLeveling || bLocalSeamLeveling)) {
// create seam vertices and edges // create seam vertices and edges
@ -8381,16 +8429,18 @@ void MeshTexture::GenerateTexture(bool bGlobalSeamLeveling, bool bLocalSeamLevel
if (bGlobalSeamLeveling) { if (bGlobalSeamLeveling) {
TD_TIMER_STARTD(); TD_TIMER_STARTD();
GlobalSeamLeveling3(); GlobalSeamLeveling3();
DEBUG_ULTIMATE("\tglobal seam leveling completed (%s)", TD_TIMER_GET_FMT().c_str()); DEBUG_EXTRA("\tglobal seam leveling completed (%s)", TD_TIMER_GET_FMT().c_str());
} }
// perform local seam leveling // perform local seam leveling
if (bLocalSeamLeveling) { if (bLocalSeamLeveling) {
TD_TIMER_STARTD(); TD_TIMER_STARTD();
LocalSeamLeveling(); // LocalSeamLeveling();
DEBUG_ULTIMATE("\tlocal seam leveling completed (%s)", TD_TIMER_GET_FMT().c_str()); LocalSeamLeveling3();
DEBUG_EXTRA("\tlocal seam leveling completed (%s)", TD_TIMER_GET_FMT().c_str());
} }
} }
DEBUG_EXTRA("seam (%s)", TD_TIMER_GET_FMT().c_str());
// merge texture patches with overlapping rectangles // merge texture patches with overlapping rectangles
for (unsigned i=0; i<texturePatches.size()-1; ++i) { for (unsigned i=0; i<texturePatches.size()-1; ++i) {
@ -9635,12 +9685,12 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
dict3 = result["result3"].cast<py::dict>(); dict3 = result["result3"].cast<py::dict>();
} }
printf("dict1 size=%d, dict2 size=%d, dict3 size=%d\n", dict1.size(), dict2.size(), dict3.size()); // printf("dict1 size=%d, dict2 size=%d, dict3 size=%d\n", dict1.size(), dict2.size(), dict3.size());
// 处理返回的可见面字典 // 处理返回的可见面字典
for (auto item : dict1) { for (auto item : dict1) {
std::string image_name = item.first.cast<std::string>(); std::string image_name = item.first.cast<std::string>();
printf("dict1 mask image name=%s\n", image_name.c_str()); // printf("dict1 mask image name=%s\n", image_name.c_str());
py::list visible_faces = item.second.cast<py::list>(); py::list visible_faces = item.second.cast<py::list>();
std::unordered_set<int> face_set; std::unordered_set<int> face_set;
@ -9657,7 +9707,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
for (auto item : dict2) { for (auto item : dict2) {
std::string image_name = item.first.cast<std::string>(); std::string image_name = item.first.cast<std::string>();
printf("dict2 mask image name=%s\n", image_name.c_str()); // printf("dict2 mask image name=%s\n", image_name.c_str());
py::list edge_faces = item.second.cast<py::list>(); py::list edge_faces = item.second.cast<py::list>();
std::unordered_set<int> face_set; std::unordered_set<int> face_set;
@ -9669,7 +9719,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
for (auto item : dict3) { for (auto item : dict3) {
std::string image_name = item.first.cast<std::string>(); std::string image_name = item.first.cast<std::string>();
printf("dict3 mask image name=%s\n", image_name.c_str()); // printf("dict3 mask image name=%s\n", image_name.c_str());
py::list delete_edge_faces = item.second.cast<py::list>(); py::list delete_edge_faces = item.second.cast<py::list>();
std::unordered_set<int> face_set; std::unordered_set<int> face_set;
@ -9761,8 +9811,7 @@ bool Scene::TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, unsi
TD_TIMER_STARTD(); TD_TIMER_STARTD();
texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview); texture.GenerateTexture(bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic, colEmpty, fSharpnessWeight, maxTextureSize, baseFileName, bOriginFaceview);
DEBUG_EXTRA("Generating texture atlas and image completed: %u patches, %u image size, %u textures (%s)", texture.texturePatches.size(), mesh.texturesDiffuse[0].width(), mesh.texturesDiffuse.size(), TD_TIMER_GET_FMT().c_str()); DEBUG_EXTRA("Generating texture atlas and image completed: %u patches, %u image size, %u textures (%s)", texture.texturePatches.size(), mesh.texturesDiffuse[0].width(), mesh.texturesDiffuse.size(), TD_TIMER_GET_FMT().c_str());
} }
#ifdef DISPLAY_DEMO #ifdef DISPLAY_DEMO
try { try {
py::scoped_interpreter guard{}; // 自动管理解释器生命周期 py::scoped_interpreter guard{}; // 自动管理解释器生命周期

Loading…
Cancel
Save