处理脸色发青问题
This commit is contained in:
1 parent
bbddc87ccc
commit
5685a46331
2 files changed
+224
-1
No files matched your search
@@ -1261,6 +1261,229 @@ bool MeshTexture::ListCameraFaces(FaceDataViewArr& facesDatas, float fOutlierThr
|
||||
}
|
||||
++progress;
|
||||
}
|
||||
|
||||
// Temp
|
||||
/*
|
||||
for (int_t idx=0; idx<(int_t)views.size(); ++idx)
|
||||
{
|
||||
#pragma omp flush (bAbort)
|
||||
if (bAbort)
|
||||
{
|
||||
++progress;
|
||||
continue;
|
||||
}
|
||||
const IIndex idxView(views[(IIndex)idx]);
|
||||
|
||||
Image& imageData = images[idxView];
|
||||
if (!imageData.IsValid()) {
|
||||
++progress;
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// load image
|
||||
unsigned level(nResolutionLevel);
|
||||
const unsigned imageSize(imageData.RecomputeMaxResolution(level, nMinResolution));
|
||||
if ((imageData.image.empty() || MAXF(imageData.width,imageData.height) != imageSize) && !imageData.ReloadImage(imageSize)) {
|
||||
#ifdef TEXOPT_USE_OPENMP
|
||||
bAbort = true;
|
||||
#pragma omp flush (bAbort)
|
||||
continue;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
imageData.UpdateCamera(scene.platforms);
|
||||
// compute gradient magnitude
|
||||
imageData.image.toGray(imageGradMag, cv::COLOR_BGR2GRAY, true);
|
||||
cv::Mat grad[2];
|
||||
mGrad[0].resize(imageGradMag.rows, imageGradMag.cols);
|
||||
grad[0] = cv::Mat(imageGradMag.rows, imageGradMag.cols, cv::DataType<real>::type, (void*)mGrad[0].data());
|
||||
mGrad[1].resize(imageGradMag.rows, imageGradMag.cols);
|
||||
grad[1] = cv::Mat(imageGradMag.rows, imageGradMag.cols, cv::DataType<real>::type, (void*)mGrad[1].data());
|
||||
|
||||
cv::Sobel(imageGradMag, grad[0], cv::DataType<real>::type, 1, 0, 3, 1.0/8.0);
|
||||
cv::Sobel(imageGradMag, grad[1], cv::DataType<real>::type, 0, 1, 3, 1.0/8.0);
|
||||
|
||||
(TImage<real>::EMatMap)imageGradMag = (mGrad[0].cwiseAbs2()+mGrad[1].cwiseAbs2()).cwiseSqrt();
|
||||
// apply some blur on the gradient to lower noise/glossiness effects onto face-quality score
|
||||
cv::GaussianBlur(imageGradMag, imageGradMag, cv::Size(15, 15), 0, 0, cv::BORDER_DEFAULT);
|
||||
// select faces inside view frustum
|
||||
Mesh::FaceIdxArr cameraFaces;
|
||||
Mesh::FacesInserter inserter(cameraFaces);
|
||||
const TFrustum<float,5> frustum(Matrix3x4f(imageData.camera.P), (float)imageData.width, (float)imageData.height);
|
||||
octree.Traverse(frustum, inserter);
|
||||
// project all triangles in this view and keep the closest ones
|
||||
faceMap.create(imageData.GetSize());
|
||||
depthMap.create(imageData.GetSize());
|
||||
|
||||
std::unordered_set<FIndex> tempFaces;
|
||||
{
|
||||
// RasterMesh rasterer(vertices, imageData.camera, depthMap, faceMap);
|
||||
RasterMesh rasterer(*this, vertices, imageData.camera, depthMap, faceMap, scene.mesh, false);
|
||||
RasterMesh::Triangle triangle;
|
||||
RasterMesh::TriangleRasterizer triangleRasterizer(triangle, rasterer);
|
||||
if (nIgnoreMaskLabel >= 0) {
|
||||
// import mask
|
||||
BitMatrix bmask;
|
||||
// std::cout << "nIgnoreMaskLabel is open" << std::endl;
|
||||
DepthEstimator::ImportIgnoreMask(imageData, imageData.GetSize(), (uint16_t)OPTDENSE::nIgnoreMaskLabel, bmask, &rasterer.mask);
|
||||
} else if (nIgnoreMaskLabel == -1) {
|
||||
// creating mask to discard invalid regions created during image radial undistortion
|
||||
rasterer.mask = DetectInvalidImageRegions(imageData.image);
|
||||
#if TD_VERBOSE != TD_VERBOSE_OFF
|
||||
if (VERBOSITY_LEVEL > 2)
|
||||
cv::imwrite(String::FormatString("umask%04d.png", idxView), rasterer.mask);
|
||||
#endif
|
||||
}
|
||||
rasterer.Clear();
|
||||
for (FIndex idxFace : cameraFaces) {
|
||||
rasterer.validFace = true;
|
||||
const Face& facet = faces[idxFace];
|
||||
rasterer.idxFace = idxFace;
|
||||
|
||||
bool bExistFace = facesDatas[idxFace].empty();
|
||||
|
||||
if (scene.is_face_visible(strName.c_str(), idxFace) || bExistFace)
|
||||
{
|
||||
rasterer.Project(facet, triangleRasterizer);
|
||||
if (!rasterer.validFace)
|
||||
rasterer.Project(facet, triangleRasterizer);
|
||||
}
|
||||
}
|
||||
|
||||
tempFaces = PerformLocalDepthConsistencyCheck(depthMap, faceMap, scene.mesh, idxView, strName);
|
||||
}
|
||||
|
||||
// compute the projection area of visible faces
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
CLISTDEF0IDX(uint32_t,FIndex) areas(faces.size());
|
||||
areas.Memset(0);
|
||||
#endif
|
||||
|
||||
#ifdef TEXOPT_USE_OPENMP
|
||||
#pragma omp critical
|
||||
#endif
|
||||
|
||||
{
|
||||
for (int j=0; j<faceMap.rows; ++j) {
|
||||
for (int i=0; i<faceMap.cols; ++i) {
|
||||
const FIndex& idxFace = faceMap(j,i);
|
||||
// ASSERT((idxFace == NO_ID && depthMap(j,i) == 0) || (idxFace != NO_ID && depthMap(j,i) > 0));
|
||||
|
||||
if (idxFace == NO_ID)
|
||||
continue;
|
||||
|
||||
FaceDataArr& faceDatas = facesDatas[idxFace];
|
||||
|
||||
const Pixel8U& pixel = imageData.image(j, i);
|
||||
// 假设是8位图像,RGB三个通道任一超过250即视为过曝
|
||||
if (pixel.r > 250 || pixel.g > 250 || pixel.b > 250) {
|
||||
// continue;
|
||||
}
|
||||
|
||||
float brightnessPerceptual = (0.299f * pixel.r + 0.587f * pixel.g + 0.114f * pixel.b) / 255.0f;
|
||||
// printf("brightnessPerceptual=%f\n", brightnessPerceptual);
|
||||
|
||||
if (brightnessPerceptual>0.95f)
|
||||
continue;
|
||||
|
||||
{
|
||||
if (depthMap(j,i)>999.0f)
|
||||
{
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
uint32_t& area = areas[idxFace];
|
||||
if (area++ == 0) {
|
||||
#else
|
||||
if (faceDatas.empty() || faceDatas.back().idxView != idxView) {
|
||||
#endif
|
||||
// create new face-data
|
||||
FaceData& faceData = faceDatas.emplace_back();
|
||||
faceData.idxView = idxView;
|
||||
faceData.quality = imageGradMag(j,i);
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
faceData.color = imageData.image(j,i);
|
||||
#endif
|
||||
faceData.bInvalidFacesRelative = true;
|
||||
} else {
|
||||
// update face-data
|
||||
ASSERT(!faceDatas.empty());
|
||||
FaceData& faceData = faceDatas.back();
|
||||
ASSERT(faceData.idxView == idxView);
|
||||
faceData.quality = imageGradMag(j,i);
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
faceData.color = Color(imageData.image(j,i));
|
||||
#endif
|
||||
faceData.bInvalidFacesRelative = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t& area = areas[idxFace];
|
||||
if (area++ == 0) {
|
||||
// create new face-data
|
||||
FaceData& faceData = faceDatas.emplace_back();
|
||||
faceData.idxView = idxView;
|
||||
faceData.quality = imageGradMag(j,i);
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
faceData.color = imageData.image(j,i);
|
||||
#endif
|
||||
if (depthMap(j,i)>999.0f)
|
||||
faceData.bInvalidFacesRelative = true;
|
||||
} else {
|
||||
// update face-data
|
||||
ASSERT(!faceDatas.empty());
|
||||
FaceData& faceData = faceDatas.back();
|
||||
ASSERT(faceData.idxView == idxView);
|
||||
faceData.quality += imageGradMag(j,i);
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
faceData.color += Color(imageData.image(j,i));
|
||||
#endif
|
||||
if (depthMap(j,i)>999.0f)
|
||||
faceData.bInvalidFacesRelative = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// adjust face quality with camera angle relative to face normal
|
||||
// tries to increase chances of a camera with perpendicular view on the surface (smoothened normals) to be selected
|
||||
FOREACH(idxFace, facesDatas) {
|
||||
FaceDataArr& faceDatas = facesDatas[idxFace];
|
||||
if (faceDatas.empty() || faceDatas.back().idxView != idxView)
|
||||
continue;
|
||||
const Face& f = faces[idxFace];
|
||||
const Vertex faceCenter((vertices[f[0]] + vertices[f[1]] + vertices[f[2]]) / 3.f);
|
||||
const Point3f camDir(Cast<Mesh::Type>(imageData.camera.C) - faceCenter);
|
||||
const Normal& faceNormal = scene.mesh.faceNormals[idxFace];
|
||||
const float cosFaceCam(MAXF(0.001f, ComputeAngle(camDir.ptr(), faceNormal.ptr())));
|
||||
faceDatas.back().quality *= SQUARE(cosFaceCam);
|
||||
}
|
||||
#if TEXOPT_FACEOUTLIER != TEXOPT_FACEOUTLIER_NA
|
||||
FOREACH(idxFace, areas) {
|
||||
const uint32_t& area = areas[idxFace];
|
||||
if (area > 0) {
|
||||
Color& color = facesDatas[idxFace].back().color;
|
||||
color = RGB2YCBCR(Color(color * (1.f/(float)area)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++progress;
|
||||
}
|
||||
// */
|
||||
// Temp
|
||||
|
||||
#ifdef TEXOPT_USE_OPENMP
|
||||
if (bAbort)
|
||||
return false;
|
||||
|
||||
@@ -1353,7 +1353,7 @@ class ModelProcessor:
|
||||
face_visible = v0_visible | v1_visible | v2_visible
|
||||
|
||||
# 使用与CPU版本相同的后续处理
|
||||
shrunk_visibility = self._shrink_face_visibility(face_visible.cpu().numpy(), 10)
|
||||
shrunk_visibility = self._shrink_face_visibility(face_visible.cpu().numpy(), 6)
|
||||
expanded_visibility = self._expand_face_visibility(face_visible.cpu().numpy(), 30)
|
||||
shrunk_visibility2 = self._shrink_face_visibility(face_visible.cpu().numpy(), 50)
|
||||
expanded_edge = expanded_visibility & ~shrunk_visibility2
|
||||
|
||||
Reference in new issue
Block a user