Browse Source

优化性能

ManualUV
hesuicong 1 month ago
parent
commit
aadfbb4b08
  1. 212
      libs/MVS/SceneTexture.cpp

212
libs/MVS/SceneTexture.cpp

@ -9781,7 +9781,7 @@ Pixel8U SampleImageBilinear(const Image8U3& image, const Point2f& point) { @@ -9781,7 +9781,7 @@ Pixel8U SampleImageBilinear(const Image8U3& image, const Point2f& point) {
return result;
}
void FillTextureGaps(Image8U3& textureAtlas, const Mesh::TexCoordArr& faceTexcoords,
void FillTextureGaps2(Image8U3& textureAtlas, const Mesh::TexCoordArr& faceTexcoords,
FIndex nFaces, const MeshTexture::LabelArr& faceLabels,
const IIndexArr& views, int textureSize, Pixel8U colEmpty)
{
@ -9926,6 +9926,213 @@ void FillTextureGaps(Image8U3& textureAtlas, const Mesh::TexCoordArr& faceTexcoo @@ -9926,6 +9926,213 @@ void FillTextureGaps(Image8U3& textureAtlas, const Mesh::TexCoordArr& faceTexcoo
inpaintResult.copyTo(textureAtlas);
}
DEBUG_EXTRA("纹理间隙填充完成");
}// 修改TextureGrid结构体,在构造函数中传入纹理大小
struct TextureGrid {
std::vector<std::vector<FIndex>> grid;
float cellSize;
int gridSize;
int textureSize; // 添加纹理大小成员变量
TextureGrid(int _textureSize, int cellCount) : textureSize(_textureSize) {
cellSize = (float)textureSize / cellCount;
gridSize = cellCount;
grid.resize(gridSize * gridSize);
}
void AddTriangle(FIndex faceIdx, const TexCoord* uvCoords, int _textureSize) { // 添加纹理大小参数
int minX = _textureSize, maxX = 0;
int minY = _textureSize, maxY = 0;
for (int i = 0; i < 3; ++i) {
int px = std::max(0, std::min(_textureSize - 1, (int)(uvCoords[i].x * _textureSize)));
int py = std::max(0, std::min(_textureSize - 1, (int)(uvCoords[i].y * _textureSize)));
minX = std::min(minX, px);
maxX = std::max(maxX, px);
minY = std::min(minY, py);
maxY = std::max(maxY, py);
}
int cellMinX = std::max(0, (int)(minX / cellSize));
int cellMaxX = std::min(gridSize-1, (int)(maxX / cellSize));
int cellMinY = std::max(0, (int)(minY / cellSize));
int cellMaxY = std::min(gridSize-1, (int)(maxY / cellSize));
for (int cy = cellMinY; cy <= cellMaxY; ++cy) {
for (int cx = cellMinX; cx <= cellMaxX; ++cx) {
grid[cy * gridSize + cx].push_back(faceIdx);
}
}
}
const std::vector<FIndex>& GetTrianglesInCell(int x, int y) const {
return grid[y * gridSize + x];
}
};
void GenerateDistanceFieldFast(cv::Mat& distanceField, cv::Mat& nearestFaceIdx,
const std::vector<cv::Point>& seedPoints,
int textureSize) {
// 使用跳点传播算法
distanceField = cv::Mat::zeros(textureSize, textureSize, CV_32FC1);
nearestFaceIdx = cv::Mat::zeros(textureSize, textureSize, CV_32SC1);
// 初始化距离场
distanceField.setTo(std::numeric_limits<float>::max());
// 标记种子点
for (const auto& pt : seedPoints) {
distanceField.at<float>(pt) = 0;
nearestFaceIdx.at<int>(pt) = pt.y * textureSize + pt.x; // 存储自身索引
}
// 跳点传播
for (int step = textureSize / 2; step >= 1; step /= 2) {
#pragma omp parallel for collapse(2)
for (int y = 0; y < textureSize; ++y) {
for (int x = 0; x < textureSize; ++x) {
float minDist = distanceField.at<float>(y, x);
int bestIdx = nearestFaceIdx.at<int>(y, x);
for (int dy = -1; dy <= 1; dy += 2) {
for (int dx = -1; dx <= 1; dx += 2) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < textureSize && ny >= 0 && ny < textureSize) {
float dist = distanceField.at<float>(ny, nx) +
sqrtf((dx*dx + dy*dy) * step * step);
if (dist < minDist) {
minDist = dist;
bestIdx = nearestFaceIdx.at<int>(ny, nx);
}
}
}
}
distanceField.at<float>(y, x) = minDist;
nearestFaceIdx.at<int>(y, x) = bestIdx;
}
}
}
}void FillTextureGaps(Image8U3& textureAtlas, const Mesh::TexCoordArr& faceTexcoords,
FIndex nFaces, const MeshTexture::LabelArr& faceLabels,
int textureSize, Pixel8U colEmpty)
{
DEBUG_EXTRA("开始填充纹理间隙...");
// 创建距离场
cv::Mat distanceField(textureSize, textureSize, CV_32FC1, cv::Scalar(std::numeric_limits<float>::max()));
cv::Mat nearestPixelIdx(textureSize, textureSize, CV_32SC1, cv::Scalar(-1));
// 1. 初始化种子点(已有纹理的像素)
for (int y = 0; y < textureSize; ++y) {
for (int x = 0; x < textureSize; ++x) {
const Pixel8U& pixel = textureAtlas(y, x);
if (pixel[0] != colEmpty[0] || pixel[1] != colEmpty[1] || pixel[2] != colEmpty[2]) {
distanceField.at<float>(y, x) = 0.0f;
nearestPixelIdx.at<int>(y, x) = y * textureSize + x;
}
}
}
// 2. 跳点传播算法
for (int step = textureSize / 2; step >= 1; step /= 2) {
for (int y = 0; y < textureSize; ++y) {
for (int x = 0; x < textureSize; ++x) {
float minDist = distanceField.at<float>(y, x);
int bestIdx = nearestPixelIdx.at<int>(y, x);
for (int dy = -1; dy <= 1; dy += 2) {
for (int dx = -1; dx <= 1; dx += 2) {
int nx = x + dx * step;
int ny = y + dy * step;
if (nx >= 0 && nx < textureSize && ny >= 0 && ny < textureSize) {
float neighborDist = distanceField.at<float>(ny, nx);
float dist = neighborDist + sqrtf((dx*dx + dy*dy) * step * step);
if (dist < minDist && nearestPixelIdx.at<int>(ny, nx) != -1) {
minDist = dist;
bestIdx = nearestPixelIdx.at<int>(ny, nx);
}
}
}
}
if (bestIdx != -1 && minDist < distanceField.at<float>(y, x)) {
distanceField.at<float>(y, x) = minDist;
nearestPixelIdx.at<int>(y, x) = bestIdx;
}
}
}
}
// 3. 填充空白区域
const float maxFillDistance = 5.0f;
int filledCount = 0;
for (int y = 0; y < textureSize; ++y) {
for (int x = 0; x < textureSize; ++x) {
Pixel8U& pixel = textureAtlas(y, x);
if (pixel[0] == colEmpty[0] && pixel[1] == colEmpty[1] && pixel[2] == colEmpty[2]) {
int nearestIdx = nearestPixelIdx.at<int>(y, x);
float dist = distanceField.at<float>(y, x);
if (nearestIdx != -1 && dist <= maxFillDistance) {
int nx = nearestIdx % textureSize;
int ny = nearestIdx / textureSize;
pixel = textureAtlas(ny, nx);
filledCount++;
}
}
}
}
DEBUG_EXTRA("快速填充完成,填充了 %d 个像素", filledCount);
// // 4. 优化版图像修复
// cv::Mat mask = cv::Mat::zeros(textureSize, textureSize, CV_8UC1);
// cv::Mat textureMat = textureAtlas;
// // 使用OpenCV向量化操作
// unsigned char r = colEmpty[0];
// unsigned char g = colEmpty[1];
// unsigned char b = colEmpty[2];
// #pragma omp parallel for
// for (int y = 0; y < textureSize; ++y) {
// unsigned char* maskRow = mask.ptr<unsigned char>(y);
// const unsigned char* textureRow = textureMat.ptr<unsigned char>(y);
// for (int x = 0; x < textureSize; ++x) {
// int idx = x * 3;
// if (textureRow[idx] == r &&
// textureRow[idx + 1] == g &&
// textureRow[idx + 2] == b) {
// maskRow[x] = 255;
// }
// }
// }
// if (cv::countNonZero(mask) > 0) {
// // 优化inpaint参数
// int inpaintRadius = 2; // 减少修复半径
// cv::Mat inpaintResult;
// // 如果空白区域很少,使用更快的算法
// double blankRatio = cv::countNonZero(mask) / (double)(textureSize * textureSize);
// if (blankRatio < 0.01) { // 空白区域少于1%
// // 使用快速修复
// cv::dilate(textureMat, inpaintResult, cv::Mat());
// inpaintResult.copyTo(textureAtlas, mask);
// } else {
// // 使用inpaint
// cv::inpaint(textureMat, mask, inpaintResult, inpaintRadius, cv::INPAINT_TELEA);
// inpaintResult.copyTo(textureAtlas);
// }
// }
DEBUG_EXTRA("纹理间隙填充完成");
}
@ -10089,8 +10296,7 @@ Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasFromUV(const LabelArr& faceLa @@ -10089,8 +10296,7 @@ Mesh::Image8U3Arr MeshTexture::GenerateTextureAtlasFromUV(const LabelArr& faceLa
}
// 5. 添加后处理填充函数
FillTextureGaps(textureAtlas, scene.mesh.faceTexcoords, (FIndex)scene.mesh.faces.size(), faceLabels, views, textureSize, colEmpty);
FillTextureGaps(textureAtlas, scene.mesh.faceTexcoords, (FIndex)scene.mesh.faces.size(), faceLabels, textureSize, colEmpty);
// 6. 应用后处理
if (fSharpnessWeight > 0) {

Loading…
Cancel
Save