优化
This commit is contained in:
1 parent
bccd31fea6
commit
b95b9ca27a
1 file changed
+207
-40
+207
-40
@@ -4301,9 +4301,10 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
} else {
|
||||
IIndexArr selectedCams = SelectBestViews(centerFaceDatas, virtualFaceCenterFaceID, minCommonCameras, ratioAngleToQuality);
|
||||
|
||||
//*
|
||||
// 获取中心面片的法线 (注意变量名是 normalCenter, 不是 centerNormal)
|
||||
const Normal& normalCenter = scene.mesh.faceNormals[virtualFaceCenterFaceID];
|
||||
|
||||
//*
|
||||
// 过滤selectedCams:只保留夹角小于30度的视图
|
||||
IIndexArr filteredCams; // 用于存储过滤后的视图索引
|
||||
for (IIndex idxView : selectedCams) {
|
||||
@@ -4359,52 +4360,219 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
|
||||
if (angleDeg <= 45.0f)
|
||||
{
|
||||
// filteredCams.push_back(idxView);
|
||||
|
||||
//*
|
||||
float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数
|
||||
float angleScore = 1.0f - (angleDeg / 45.0f);
|
||||
float qualityScore = 0.0f;
|
||||
const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
|
||||
for (const FaceData& fd : centerFaceDatas) {
|
||||
if (fd.idxView == idxView) {
|
||||
qualityScore = fd.quality;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qualityScore = std::max(0.0f, std::min(1.0f, qualityScore));
|
||||
float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore;
|
||||
if (overallScore > 0.35f) {
|
||||
filteredCams.push_back(idxView);
|
||||
}
|
||||
//*/
|
||||
}
|
||||
filteredCams.push_back(idxView);
|
||||
|
||||
// float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数
|
||||
// float angleScore = 1.0f - (angleDeg / 45.0f);
|
||||
// float qualityScore = 0.0f;
|
||||
// const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
|
||||
// for (const FaceData& fd : centerFaceDatas) {
|
||||
// if (fd.idxView == idxView) {
|
||||
// qualityScore = fd.quality;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// qualityScore = std::max(0.0f, std::min(1.0f, qualityScore));
|
||||
// float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore;
|
||||
// if (overallScore > 0.35f) {
|
||||
// filteredCams.push_back(idxView);
|
||||
// }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// filteredCams.push_back(idxView);
|
||||
filteredCams.push_back(idxView);
|
||||
|
||||
//*
|
||||
float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数
|
||||
float angleScore = 1.0f - (angleDeg / 45.0f);
|
||||
float qualityScore = 0.0f;
|
||||
const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
|
||||
for (const FaceData& fd : centerFaceDatas) {
|
||||
if (fd.idxView == idxView) {
|
||||
qualityScore = fd.quality;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qualityScore = std::max(0.0f, std::min(1.0f, qualityScore));
|
||||
float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore;
|
||||
if (overallScore > 0.35f) {
|
||||
filteredCams.push_back(idxView);
|
||||
}
|
||||
//*/
|
||||
// float brightnessScore = CalculateBrightnessScore(imageData); // 亮度评分函数
|
||||
// float angleScore = 1.0f - (angleDeg / 45.0f);
|
||||
// float qualityScore = 0.0f;
|
||||
// const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
|
||||
// for (const FaceData& fd : centerFaceDatas) {
|
||||
// if (fd.idxView == idxView) {
|
||||
// qualityScore = fd.quality;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// qualityScore = std::max(0.0f, std::min(1.0f, qualityScore));
|
||||
// float overallScore = 0.5f * angleScore + 0.3f * brightnessScore + 0.2f * qualityScore;
|
||||
// if (overallScore > 0.35f) {
|
||||
// filteredCams.push_back(idxView);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
//*/
|
||||
|
||||
/*
|
||||
|
||||
struct CameraInfo {
|
||||
float brightness;
|
||||
float angleDeg;
|
||||
float qualityScore;
|
||||
bool isEdge;
|
||||
};
|
||||
// 修改后的代码,使用亮度统计分布过滤异常值
|
||||
IIndexArr filteredCams; // 用于存储过滤后的视图索引
|
||||
|
||||
// 步骤1: 收集所有候选相机的亮度值
|
||||
std::vector<float> allBrightnessScores;
|
||||
std::vector<std::pair<IIndex, CameraInfo>> cameraInfos; // 存储相机ID和相关信息
|
||||
|
||||
for (IIndex idxView : selectedCams) {
|
||||
const Image& imageData = images[idxView];
|
||||
|
||||
// 计算相机朝向向量
|
||||
const RMatrix& R = imageData.camera.R;
|
||||
Point3f localForward(0.0f, 0.0f, -1.0f);
|
||||
Point3f cameraForward;
|
||||
cameraForward.x = R(0,0) * localForward.x + R(0,1) * localForward.y + R(0,2) * localForward.z;
|
||||
cameraForward.y = R(1,0) * localForward.x + R(1,1) * localForward.y + R(1,2) * localForward.z;
|
||||
cameraForward.z = R(2,0) * localForward.x + R(2,1) * localForward.y + R(2,2) * localForward.z;
|
||||
|
||||
// 归一化
|
||||
float norm = std::sqrt(cameraForward.x * cameraForward.x +
|
||||
cameraForward.y * cameraForward.y +
|
||||
cameraForward.z * cameraForward.z);
|
||||
if (norm > 0.0f) {
|
||||
cameraForward.x /= norm;
|
||||
cameraForward.y /= norm;
|
||||
cameraForward.z /= norm;
|
||||
} else {
|
||||
cameraForward = Point3f(0, 0, -1);
|
||||
}
|
||||
|
||||
// 计算夹角
|
||||
Point3f normalPoint(normalCenter.x, normalCenter.y, normalCenter.z);
|
||||
float cosAngle = cameraForward.dot(normalPoint);
|
||||
float angleDeg = std::acos(cosAngle) * 180.0f / M_PI;
|
||||
|
||||
// 计算亮度分数
|
||||
float brightnessScore = CalculateBrightnessScore(imageData);
|
||||
allBrightnessScores.push_back(brightnessScore);
|
||||
|
||||
// 获取质量分数
|
||||
float qualityScore = 0.0f;
|
||||
const FaceDataArr& centerFaceDatas = facesDatas[virtualFaceCenterFaceID];
|
||||
for (const FaceData& fd : centerFaceDatas) {
|
||||
if (fd.idxView == idxView) {
|
||||
qualityScore = fd.quality;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qualityScore = std::max(0.0f, std::min(1.0f, qualityScore));
|
||||
|
||||
// 检查是否为边缘
|
||||
std::string strPath = imageData.name;
|
||||
size_t lastSlash = strPath.find_last_of("/\\");
|
||||
if (lastSlash == std::string::npos) lastSlash = 0;
|
||||
else lastSlash++;
|
||||
|
||||
size_t lastDot = strPath.find_last_of('.');
|
||||
if (lastDot == std::string::npos) lastDot = strPath.size();
|
||||
|
||||
std::string strName = strPath.substr(lastSlash, lastDot - lastSlash);
|
||||
|
||||
bool isEdge = false;
|
||||
if (!scene.is_face_delete_edge(strName, virtualFaceCenterFaceID)) {
|
||||
isEdge = scene.is_face_edge(strName, virtualFaceCenterFaceID);
|
||||
}
|
||||
|
||||
// 存储相机信息
|
||||
cameraInfos.emplace_back(idxView, CameraInfo{
|
||||
.brightness = brightnessScore,
|
||||
.angleDeg = angleDeg,
|
||||
.qualityScore = qualityScore,
|
||||
.isEdge = isEdge
|
||||
});
|
||||
}
|
||||
|
||||
float medianBrightness = 0.0f;
|
||||
// 步骤2: 计算亮度分布的统计特征
|
||||
if (!allBrightnessScores.empty()) {
|
||||
// 方法1: 使用中位数和MAD(绝对中位差) - 对异常值更鲁棒
|
||||
std::vector<float> sortedBrightness = allBrightnessScores;
|
||||
std::sort(sortedBrightness.begin(), sortedBrightness.end());
|
||||
|
||||
medianBrightness = sortedBrightness[sortedBrightness.size() / 2];
|
||||
|
||||
// 计算MAD
|
||||
std::vector<float> deviations;
|
||||
for (float brightness : allBrightnessScores) {
|
||||
deviations.push_back(std::abs(brightness - medianBrightness));
|
||||
}
|
||||
std::sort(deviations.begin(), deviations.end());
|
||||
float mad = deviations[deviations.size() / 2];
|
||||
|
||||
// 使用3倍MAD作为阈值(通常2-3倍MAD是常用阈值)
|
||||
float lowerThreshold = medianBrightness - 2.5f * mad;
|
||||
float upperThreshold = medianBrightness + 2.5f * mad;
|
||||
|
||||
// 方法2: 使用四分位距(IQR) - 备选方法
|
||||
if (sortedBrightness.size() >= 4) {
|
||||
int q1_index = sortedBrightness.size() / 4;
|
||||
int q3_index = 3 * sortedBrightness.size() / 4;
|
||||
float q1 = sortedBrightness[q1_index];
|
||||
float q3 = sortedBrightness[q3_index];
|
||||
float iqr = q3 - q1;
|
||||
|
||||
// 使用1.5倍IQR规则
|
||||
float iqrLower = q1 - 1.5f * iqr;
|
||||
float iqrUpper = q3 + 1.5f * iqr;
|
||||
|
||||
// 也可以结合两种方法
|
||||
lowerThreshold = std::max(lowerThreshold, iqrLower);
|
||||
upperThreshold = std::min(upperThreshold, iqrUpper);
|
||||
}
|
||||
|
||||
// 步骤3: 根据统计特征过滤相机
|
||||
for (const auto& [idxView, info] : cameraInfos) {
|
||||
// 检查亮度是否在正常范围内
|
||||
if (info.brightness < lowerThreshold || info.brightness > upperThreshold) {
|
||||
// printf("过滤相机 %d: 亮度 %.3f 超出范围 [%.3f, %.3f]\n",
|
||||
// idxView, info.brightness, lowerThreshold, upperThreshold);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据是否为边缘面使用不同的参数
|
||||
float angleLimit = info.isEdge ? 45.0f : 60.0f;
|
||||
float scoreThreshold = info.isEdge ? 0.4f : 0.3f;
|
||||
|
||||
if (info.angleDeg <= angleLimit) {
|
||||
float angleScore = 1.0f - (info.angleDeg / angleLimit);
|
||||
float overallScore = 0.5f * angleScore + 0.3f * info.brightness + 0.2f * info.qualityScore;
|
||||
|
||||
if (overallScore > scoreThreshold) {
|
||||
filteredCams.push_back(idxView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有足够的相机满足统计条件,可以放宽阈值或使用原始方法
|
||||
if (filteredCams.size() < 3 && !cameraInfos.empty()) {
|
||||
// 回退到简单方法:选择亮度最接近中位数的前N个相机
|
||||
std::vector<std::pair<IIndex, float>> brightnessDifferences;
|
||||
|
||||
for (const auto& cameraInfoPair : cameraInfos) {
|
||||
IIndex idxView = cameraInfoPair.first;
|
||||
CameraInfo info = cameraInfoPair.second;
|
||||
if (info.isEdge ? (info.angleDeg <= 45.0f) : (info.angleDeg <= 60.0f)) {
|
||||
// 计算亮度与中位数的差异
|
||||
float brightnessDiff = std::abs(info.brightness - medianBrightness);
|
||||
brightnessDifferences.emplace_back(idxView, brightnessDiff);
|
||||
}
|
||||
}
|
||||
|
||||
// 按亮度差异排序,选择差异最小的
|
||||
std::sort(brightnessDifferences.begin(), brightnessDifferences.end(),
|
||||
[](const auto& a, const auto& b) { return a.second < b.second; });
|
||||
|
||||
int neededCount = std::min(5, (int)brightnessDifferences.size());
|
||||
for (int i = 0; i < neededCount; i++) {
|
||||
filteredCams.push_back(brightnessDifferences[i].first);
|
||||
}
|
||||
}
|
||||
//*/
|
||||
|
||||
// 确保 selectedCams 是非 const 的,才能对其进行赋值
|
||||
// 例如,其声明应为:IIndexArr selectedCams = ...; (不能是 const IIndexArr)
|
||||
@@ -4420,7 +4588,6 @@ bool MeshTexture::CreateVirtualFaces62(FaceDataViewArr& facesDatas, FaceDataView
|
||||
selectedCams = filteredCams;
|
||||
isVirtualFace[virtualFaceCenterFaceID] = true;
|
||||
}
|
||||
//*/
|
||||
|
||||
currentVirtualFaceQueue.AddTail(virtualFaceCenterFaceID);
|
||||
queuedFaces.clear();
|
||||
|
||||
Reference in new issue
Block a user