中间版本保存
This commit is contained in:
1 parent
3adc1c012a
commit
b0c165499c
1 file changed
+36
-249
+36
-249
@@ -6935,6 +6935,7 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
||||
// printf("FaceViewSelection3 2 scene.mesh.vertices.size=%d\n", scene.mesh.vertices.size());
|
||||
|
||||
bool bUseVirtualFaces(minCommonCameras > 0);
|
||||
bUseVirtualFaces = false;
|
||||
|
||||
// list all views for each face
|
||||
FaceDataViewArr facesDatas;
|
||||
@@ -7673,263 +7674,49 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
||||
|
||||
if (!bUseVirtualFaces)
|
||||
{
|
||||
// assign the best view to each face
|
||||
labels.resize(faces.size());
|
||||
{
|
||||
// normalize quality values
|
||||
float maxQuality(0);
|
||||
for (const FaceDataArr& faceDatas: facesDatas) {
|
||||
for (const FaceData& faceData: faceDatas)
|
||||
if (maxQuality < faceData.quality)
|
||||
maxQuality = faceData.quality;
|
||||
}
|
||||
Histogram32F hist(std::make_pair(0.f, maxQuality), 1000);
|
||||
for (const FaceDataArr& faceDatas: facesDatas) {
|
||||
for (const FaceData& faceData: faceDatas)
|
||||
hist.Add(faceData.quality);
|
||||
}
|
||||
const float normQuality(hist.GetApproximatePermille(0.95f));
|
||||
// 分配最佳视图给每个面片
|
||||
labels.resize(faces.size());
|
||||
labelsInvalid.resize(faces.size());
|
||||
|
||||
FOREACH(l, labelsInvalid) {
|
||||
labelsInvalid[l] = NO_ID;
|
||||
}
|
||||
|
||||
#if TEXOPT_INFERENCE == TEXOPT_INFERENCE_LBP
|
||||
// initialize inference structures
|
||||
const LBPInference::EnergyType MaxEnergy(fRatioDataSmoothness*(LBPInference::EnergyType)LBPInference::MaxEnergy);
|
||||
LBPInference inference; {
|
||||
inference.SetNumNodes(faces.size());
|
||||
inference.SetSmoothCost(SmoothnessPotts);
|
||||
// inference.SetSmoothCost(SmoothnessLinear);
|
||||
// inference.SetSmoothCost(NewSmoothness);
|
||||
// 直接为每个面片选择最佳视图(跳过推理)
|
||||
FOREACH(f, faces) {
|
||||
const FaceDataArr& faceDatas = facesDatas[f];
|
||||
if (faceDatas.empty()) {
|
||||
labels[f] = NO_ID;
|
||||
continue;
|
||||
}
|
||||
|
||||
EdgeOutIter ei, eie;
|
||||
FOREACH(f, faces) {
|
||||
for (boost::tie(ei, eie) = boost::out_edges(f, graph); ei != eie; ++ei) {
|
||||
ASSERT(f == (FIndex)ei->m_source);
|
||||
const FIndex fAdj((FIndex)ei->m_target);
|
||||
if (f < fAdj) // add edges only once
|
||||
inference.SetNeighbors(f, fAdj);
|
||||
float bestQuality = -1.0f;
|
||||
IIndex bestView = NO_ID;
|
||||
bool bBestIsInvalid = false;
|
||||
|
||||
for (const FaceData& fd : faceDatas) {
|
||||
// 跳过无效视图(根据你的需求决定是否跳过)
|
||||
if (fd.bInvalidFacesRelative) {
|
||||
// 如果没有有效视图,才考虑无效视图
|
||||
if (bestView == NO_ID) {
|
||||
bestView = fd.idxView;
|
||||
bestQuality = fd.quality;
|
||||
bBestIsInvalid = true;
|
||||
}
|
||||
// set costs for label 0 (undefined)
|
||||
inference.SetDataCost((Label)0, f, MaxEnergy);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//*
|
||||
for (const FaceDataArr& faceDatas : facesDatas) {
|
||||
for (const FaceData& faceData : faceDatas) {
|
||||
if (faceData.quality > maxQuality)
|
||||
maxQuality = faceData.quality;
|
||||
}
|
||||
}
|
||||
for (const FaceDataArr& faceDatas : facesDatas) {
|
||||
for (const FaceData& faceData : faceDatas)
|
||||
hist.Add(faceData.quality);
|
||||
}
|
||||
|
||||
FOREACH(f, facesDatas) {
|
||||
// if (scene.mesh.invalidFacesRelative.data.contains(f))
|
||||
// continue;
|
||||
|
||||
const FaceDataArr& faceDatas = facesDatas[f];
|
||||
const size_t numViews = faceDatas.size();
|
||||
const unsigned minSingleView = 6; // 与虚拟面模式相同的阈值
|
||||
|
||||
bool bInvalidFacesRelative = false;
|
||||
IIndex invalidView;
|
||||
float invalidQuality;
|
||||
|
||||
// if (numViews <= minSingleView) {
|
||||
if (true) {
|
||||
|
||||
std::vector<std::pair<float, IIndex>> sortedViews;
|
||||
sortedViews.reserve(faceDatas.size());
|
||||
for (const FaceData& fd : faceDatas) {
|
||||
|
||||
if (fd.bInvalidFacesRelative)
|
||||
{
|
||||
bInvalidFacesRelative = true;
|
||||
// sortedViews.emplace_back(fd.quality, fd.idxView);
|
||||
invalidView = fd.idxView;
|
||||
invalidQuality = fd.quality;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (fd.quality<=999.0)
|
||||
{
|
||||
sortedViews.emplace_back(fd.quality, fd.idxView);
|
||||
// printf("1fd.quality=%f\n", fd.quality);
|
||||
}
|
||||
// else
|
||||
// printf("2fd.quality=%f\n", fd.quality);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(sortedViews.begin(), sortedViews.end(),
|
||||
[](const auto& a, const auto& b) { return a.first > b.first; });
|
||||
// 设置数据成本:最佳视角成本最低,其他按质量排序递增
|
||||
const float baseCostScale = 0.1f; // 基础成本缩放系数
|
||||
const float costStep = 0.3f; // 相邻视角成本增量
|
||||
|
||||
for (const auto& image : images)
|
||||
{
|
||||
// printf("image name=%s\n", image.name.c_str());
|
||||
}
|
||||
|
||||
if (bInvalidFacesRelative && sortedViews.size() == 0)
|
||||
{
|
||||
// const Label label = (Label)sortedViews[0].second + 1;
|
||||
const Label label = (Label)invalidView + 1;
|
||||
float cost = (1.f - invalidQuality / normQuality) * MaxEnergy;
|
||||
// float cost = 0;
|
||||
inference.SetDataCost(label, f, cost);
|
||||
continue;
|
||||
}
|
||||
|
||||
// printf("sortedViews size=%d\n", sortedViews.size());
|
||||
for (size_t i = 0; i < sortedViews.size(); ++i) {
|
||||
const Label label = (Label)sortedViews[i].second + 1;
|
||||
float cost;
|
||||
|
||||
std::string strPath = images[label-1].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);
|
||||
|
||||
if (i == 0) {
|
||||
// if (true) {
|
||||
// 最佳视角
|
||||
// cost = (1.f - sortedViews[i].first / normQuality) * MaxEnergy * baseCostScale;
|
||||
cost = (1.f - sortedViews[i].first / normQuality) * MaxEnergy;
|
||||
// cost = 0;
|
||||
inference.SetDataCost(label, f, cost);
|
||||
} else {
|
||||
// 其他视角:成本随排名线性增加
|
||||
int stepIndex = i;
|
||||
// if (i > 3)
|
||||
// stepIndex = i - 3;
|
||||
cost = MaxEnergy * (baseCostScale + costStep * stepIndex);
|
||||
// 确保成本不超过MaxEnergy
|
||||
cost = std::min(cost, MaxEnergy);
|
||||
// cost = MaxEnergy;
|
||||
inference.SetDataCost(label, f, cost);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (const FaceData& fd : faceDatas) {
|
||||
const Label label = (Label)fd.idxView + 1;
|
||||
const float normalizedQuality = fd.quality / normQuality;
|
||||
const float cost = (1.f - normalizedQuality) * MaxEnergy;
|
||||
inference.SetDataCost(label, f, cost);
|
||||
}
|
||||
if (fd.quality > bestQuality) {
|
||||
bestQuality = fd.quality;
|
||||
bestView = fd.idxView;
|
||||
bBestIsInvalid = false;
|
||||
}
|
||||
}
|
||||
//*/
|
||||
|
||||
// assign the optimal view (label) to each face
|
||||
// (label 0 is reserved as undefined)
|
||||
inference.Optimize();
|
||||
|
||||
// extract resulting labeling
|
||||
labels.Memset(0xFF);
|
||||
FOREACH(l, labels) {
|
||||
const Label label(inference.GetLabel(l));
|
||||
ASSERT(label < images.size()+1);
|
||||
if (label > 0)
|
||||
labels[l] = label-1;
|
||||
|
||||
labels[f] = bestView;
|
||||
if (bBestIsInvalid) {
|
||||
labelsInvalid[f] = bestView;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEXOPT_INFERENCE == TEXOPT_INFERENCE_TRWS
|
||||
// find connected components
|
||||
ASSERT((FIndex)boost::num_vertices(graph) == faces.size());
|
||||
components.resize(faces.size());
|
||||
const FIndex nComponents(boost::connected_components(graph, components.data()));
|
||||
|
||||
// map face ID from global to component space
|
||||
typedef cList<NodeID, NodeID, 0, 128, NodeID> NodeIDs;
|
||||
NodeIDs nodeIDs(faces.size());
|
||||
NodeIDs sizes(nComponents);
|
||||
sizes.Memset(0);
|
||||
FOREACH(c, components)
|
||||
nodeIDs[c] = sizes[components[c]]++;
|
||||
|
||||
// initialize inference structures
|
||||
const LabelID numLabels(images.size()+1);
|
||||
CLISTDEFIDX(TRWSInference, FIndex) inferences(nComponents);
|
||||
FOREACH(s, sizes) {
|
||||
const NodeID numNodes(sizes[s]);
|
||||
ASSERT(numNodes > 0);
|
||||
if (numNodes <= 1)
|
||||
continue;
|
||||
TRWSInference& inference = inferences[s];
|
||||
inference.Init(numNodes, numLabels);
|
||||
}
|
||||
|
||||
// set data costs
|
||||
{
|
||||
// add nodes
|
||||
CLISTDEF0(EnergyType) D(numLabels);
|
||||
FOREACH(f, facesDatas) {
|
||||
TRWSInference& inference = inferences[components[f]];
|
||||
if (inference.IsEmpty())
|
||||
continue;
|
||||
D.MemsetValue(MaxEnergy);
|
||||
const FaceDataArr& faceDatas = facesDatas[f];
|
||||
for (const FaceData& faceData: faceDatas) {
|
||||
const Label label((Label)faceData.idxView);
|
||||
const float normalizedQuality(faceData.quality>=normQuality ? 1.f : faceData.quality/normQuality);
|
||||
const EnergyType dataCost(MaxEnergy*(1.f-normalizedQuality));
|
||||
D[label] = dataCost;
|
||||
}
|
||||
const NodeID nodeID(nodeIDs[f]);
|
||||
inference.AddNode(nodeID, D.Begin());
|
||||
}
|
||||
// add edges
|
||||
EdgeOutIter ei, eie;
|
||||
FOREACH(f, faces) {
|
||||
TRWSInference& inference = inferences[components[f]];
|
||||
if (inference.IsEmpty())
|
||||
continue;
|
||||
for (boost::tie(ei, eie) = boost::out_edges(f, graph); ei != eie; ++ei) {
|
||||
ASSERT(f == (FIndex)ei->m_source);
|
||||
const FIndex fAdj((FIndex)ei->m_target);
|
||||
ASSERT(components[f] == components[fAdj]);
|
||||
if (f < fAdj) // add edges only once
|
||||
inference.AddEdge(nodeIDs[f], nodeIDs[fAdj]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assign the optimal view (label) to each face
|
||||
#ifdef TEXOPT_USE_OPENMP
|
||||
#pragma omp parallel for schedule(dynamic)
|
||||
for (int i=0; i<(int)inferences.size(); ++i) {
|
||||
#else
|
||||
FOREACH(i, inferences) {
|
||||
#endif
|
||||
TRWSInference& inference = inferences[i];
|
||||
if (inference.IsEmpty())
|
||||
continue;
|
||||
inference.Optimize();
|
||||
}
|
||||
// extract resulting labeling
|
||||
labels.Memset(0xFF);
|
||||
FOREACH(l, labels) {
|
||||
TRWSInference& inference = inferences[components[l]];
|
||||
if (inference.IsEmpty())
|
||||
continue;
|
||||
const Label label(inference.GetLabel(nodeIDs[l]));
|
||||
ASSERT(label >= 0 && label < numLabels);
|
||||
if (label < images.size())
|
||||
labels[l] = label;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user