中间版本保存
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());
|
// printf("FaceViewSelection3 2 scene.mesh.vertices.size=%d\n", scene.mesh.vertices.size());
|
||||||
|
|
||||||
bool bUseVirtualFaces(minCommonCameras > 0);
|
bool bUseVirtualFaces(minCommonCameras > 0);
|
||||||
|
bUseVirtualFaces = false;
|
||||||
|
|
||||||
// list all views for each face
|
// list all views for each face
|
||||||
FaceDataViewArr facesDatas;
|
FaceDataViewArr facesDatas;
|
||||||
@@ -7673,263 +7674,49 @@ bool MeshTexture::FaceViewSelection3( unsigned minCommonCameras, float fOutlierT
|
|||||||
|
|
||||||
if (!bUseVirtualFaces)
|
if (!bUseVirtualFaces)
|
||||||
{
|
{
|
||||||
// assign the best view to each face
|
// 分配最佳视图给每个面片
|
||||||
labels.resize(faces.size());
|
labels.resize(faces.size());
|
||||||
{
|
labelsInvalid.resize(faces.size());
|
||||||
// normalize quality values
|
|
||||||
float maxQuality(0);
|
FOREACH(l, labelsInvalid) {
|
||||||
for (const FaceDataArr& faceDatas: facesDatas) {
|
labelsInvalid[l] = NO_ID;
|
||||||
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));
|
|
||||||
|
|
||||||
#if TEXOPT_INFERENCE == TEXOPT_INFERENCE_LBP
|
// 直接为每个面片选择最佳视图(跳过推理)
|
||||||
// initialize inference structures
|
FOREACH(f, faces) {
|
||||||
const LBPInference::EnergyType MaxEnergy(fRatioDataSmoothness*(LBPInference::EnergyType)LBPInference::MaxEnergy);
|
const FaceDataArr& faceDatas = facesDatas[f];
|
||||||
LBPInference inference; {
|
if (faceDatas.empty()) {
|
||||||
inference.SetNumNodes(faces.size());
|
labels[f] = NO_ID;
|
||||||
inference.SetSmoothCost(SmoothnessPotts);
|
continue;
|
||||||
// inference.SetSmoothCost(SmoothnessLinear);
|
}
|
||||||
// inference.SetSmoothCost(NewSmoothness);
|
|
||||||
|
|
||||||
EdgeOutIter ei, eie;
|
float bestQuality = -1.0f;
|
||||||
FOREACH(f, faces) {
|
IIndex bestView = NO_ID;
|
||||||
for (boost::tie(ei, eie) = boost::out_edges(f, graph); ei != eie; ++ei) {
|
bool bBestIsInvalid = false;
|
||||||
ASSERT(f == (FIndex)ei->m_source);
|
|
||||||
const FIndex fAdj((FIndex)ei->m_target);
|
for (const FaceData& fd : faceDatas) {
|
||||||
if (f < fAdj) // add edges only once
|
// 跳过无效视图(根据你的需求决定是否跳过)
|
||||||
inference.SetNeighbors(f, fAdj);
|
if (fd.bInvalidFacesRelative) {
|
||||||
|
// 如果没有有效视图,才考虑无效视图
|
||||||
|
if (bestView == NO_ID) {
|
||||||
|
bestView = fd.idxView;
|
||||||
|
bestQuality = fd.quality;
|
||||||
|
bBestIsInvalid = true;
|
||||||
}
|
}
|
||||||
// set costs for label 0 (undefined)
|
continue;
|
||||||
inference.SetDataCost((Label)0, f, MaxEnergy);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//*
|
|
||||||
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;
|
if (fd.quality > bestQuality) {
|
||||||
IIndex invalidView;
|
bestQuality = fd.quality;
|
||||||
float invalidQuality;
|
bestView = fd.idxView;
|
||||||
|
bBestIsInvalid = false;
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//*/
|
|
||||||
|
labels[f] = bestView;
|
||||||
// assign the optimal view (label) to each face
|
if (bBestIsInvalid) {
|
||||||
// (label 0 is reserved as undefined)
|
labelsInvalid[f] = bestView;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#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