25 #include <Utils/TriangleMesh.hh>
26 #include <Base/Math/Vector.hh>
27 #include <Base/Math/Random.hh>
28 #include <Geometry/RMatrix.hh>
29 #include <MathAlgo/Lapack.hh>
30 #include <Base/Common/CompareFloatingPoint.hh>
31 #include <Filter/Gauss.hh>
32 #include <Base/Common/FileHandling.hh>
33 #include <Base/Image/ImageIO.hh>
34 #include <Base/Geometry/HomgPlane3D.hh>
35 #include <Filter/Rescale.hh>
36 #include <Base/Math/Quadric3.hh>
40 #define USE_CONTRACTION_TEST
41 #define USE_BOUNDARY_TEST
47 const double depthScale) {
48 SetParams(minCornerAngle, maxAngle, depthScale);
53 BIASERR(
"invalid texture size, not changing existing texture");
61 const double depthScale) {
62 minCornerAngle_ = minCornerAngle;
64 depthScale_ = depthScale;
77 nvec = (p2 - p1).CrossProduct(p3 - p1);
92 return (M_PI - acos(cosAlpha));
94 return acos(cosAlpha);
112 if (GetAngle(p2 - p1, p3 - p1) < minPolyAngle)
114 else if (GetAngle(p3 - p2, p1 - p2) < minPolyAngle)
116 else if (GetAngle(p1 - p3, p2 - p3) < minPolyAngle)
136 double angle = GetAngle(p1 - C, GetPlaneNormalEuclidean(p1, p2, p3));
137 return (angle <= maxAngle);
145 BIASERR(
"Texturesize != DepthMapsize \n");
150 unsigned int w = DenseDepthMap.
GetWidth();
151 unsigned int h = DenseDepthMap.
GetHeight();
152 vector<int> pointIndices;
153 pointIndices.resize(w * h);
155 meshVertices_.clear();
156 vertexNormals_.clear();
157 textureCoords_.clear();
158 triangleIndices_.clear();
160 meshVertices_.reserve(w * h);
161 vertexNormals_.reserve(w * h);
162 textureCoords_.reserve(w * h);
163 triangleIndices_.reserve(w * h * 2);
168 float texCoordOffsetX = 1.0f / float(w - 1);
169 float texCoordOffsetY = 1.0f / float(h - 1);
171 texCoord.
Set(0.0, 1.0);
177 unsigned int currentIndex = 0;
179 for (y = 0; y < h; y++) {
180 for (x = 0; x < w; x++) {
181 if (depthValues[y][x] <= 0.0) {
182 pointIndices[y * w + x] = -1;
184 pointIndices[y * w + x] = currentIndex;
185 vertexHom =
HomgPoint3D((
double) x, (
double) y, depthScale_ * (
double) depthValues[y][x]);
187 meshVertices_.push_back(vertex);
188 textureCoords_.push_back(texCoord);
191 texCoord[0] += texCoordOffsetX;
194 texCoord[1] -= texCoordOffsetY;
199 int index0, index1, index2;
200 for (y = 0; y < h; y++) {
201 for (x = 0; x < w - 1; x++) {
209 index0 = pointIndices[y * w + x];
210 index1 = pointIndices[y * w + x + 1];
211 index2 = pointIndices[(y + 1) * w + x];
212 if (index0 > (-1) && index1 > (-1) && index2 > (-1)) {
213 triangle.
Set(index2, index1, index0);
214 if (AcceptPolyCornerAngles(meshVertices_[index0], meshVertices_[index1],
215 meshVertices_[index2], minCornerAngle_))
216 triangleIndices_.push_back(triangle);
226 index2 = pointIndices[y * w + x];
227 index1 = pointIndices[y * w + x + 1];
228 index0 = pointIndices[(y - 1) * w + x + 1];
229 if (index0 > (-1) && index1 > (-1) && index2 > (-1)) {
230 triangle.
Set(index2, index1, index0);
231 if (AcceptPolyCornerAngles(meshVertices_[index0], meshVertices_[index1],
232 meshVertices_[index2], minCornerAngle_))
233 triangleIndices_.push_back(triangle);
244 if (triangleIndices_.empty())
257 GenerateDenseMesh(DenseDepthMap,P,Texture,P);
273 return GenerateDenseMesh(DenseDepthMap, pP, Texture, pP);
280 const unsigned int distBetweenPoints) {
281 unsigned int w = DenseDepthMap.
GetWidth();
282 unsigned int h = DenseDepthMap.
GetHeight();
283 return GenerateDenseMesh(DenseDepthMap, P, Texture, TexP, 0, 0, w, h, distBetweenPoints);
286 Vector2<float> ImageToTexCoordinates(
float x0,
float y0,
unsigned int w,
unsigned int h) {
287 float texCoordOffsetX = 1.0f / float(w - 1);
288 float texCoordOffsetY = 1.0f / float(h - 1);
290 texCoord.
Set(x0 * texCoordOffsetX, 1.0f - y0 * texCoordOffsetY);
298 const unsigned int y0,
const unsigned int width,
299 const unsigned int height,
300 const unsigned int distBetweenPoints) {
303 if (width <= 0 || height <= 0) {
304 BIASERR(
"tile width is too small!");
311 unsigned int tw = Texture.
GetWidth();
313 vector<int> pointIndices;
314 pointIndices.resize(width * height);
316 meshVertices_.clear();
317 vertexNormals_.clear();
318 textureCoords_.clear();
319 triangleIndices_.clear();
321 meshVertices_.reserve(width * height);
322 vertexNormals_.reserve(width * height);
323 textureCoords_.reserve(width * height);
324 triangleIndices_.reserve(width * height * 2);
337 unsigned int currentIndex = 0;
340 for (y = 0; y < height; y++) {
341 for (x = 0; x < width; x++) {
342 if (depthValues[y0 + y][x0 + x] < 1e-5) {
343 pointIndices[y * width + x] = -1;
347 * depthValues[y + y0][x0 + x]);
349 if (vertex.
NormL2() > 1e-10) {
354 double u = uv[0] / float(tw - 1);
355 double v = 1 - uv[1] / float(th - 1);
356 texCoord.
Set(
float(u),
float(v));
359 meshVertices_.push_back(vertex);
360 textureCoords_.push_back(texCoord);
361 pointIndices[y * width + x] = currentIndex;
364 pointIndices[y * width + x] = -1;
368 BIASASSERT(meshVertices_.size()==currentIndex);
370 if (!meshVertices_.empty()) {
371 BIASASSERT(meshVertices_.back().NormL2()>1e-10);
379 int index0, index1, index2;
381 for (y = 0; y < height; y += distBetweenPoints) {
382 for (x = 0; x < width - 1; x += distBetweenPoints) {
389 if (y < height - 1) {
390 index0 = pointIndices[y * width + x];
391 index1 = pointIndices[y * width + x + 1];
392 index2 = pointIndices[(y + 1) * width + x];
393 if (index0 > (-1) && index1 > (-1) && index2 > (-1)) {
406 triangle.
Set(index2, index1, index0);
408 if (AcceptPolyCornerAngles(meshVertices_[index0], meshVertices_[index1],
409 meshVertices_[index2], minCornerAngle_)
410 && AcceptPolyPlanViewAngle(meshVertices_[index0], meshVertices_[index1],
411 meshVertices_[index2], C, maxAngle_)) {
412 triangleIndices_.push_back(triangle);
425 index2 = pointIndices[y * width + x];
426 index1 = pointIndices[y * width + x + 1];
427 index0 = pointIndices[(y - 1) * width + x + 1];
428 if (index0 > (-1) && index1 > (-1) && index2 > (-1)) {
429 triangle.
Set(index2, index1, index0);
431 if (AcceptPolyCornerAngles(meshVertices_[index0], meshVertices_[index1],
432 meshVertices_[index2], minCornerAngle_)
433 && AcceptPolyPlanViewAngle(meshVertices_[index0], meshVertices_[index1],
434 meshVertices_[index2], C, maxAngle_)) {
435 triangleIndices_.push_back(triangle);
448 if (triangleIndices_.empty()) {
465 int UpperLeftX, UpperLeftY, LowerRightX, LowerRightY;
466 CutOut.
GetCorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
473 K[0][2] -= double(UpperLeftX);
474 K[1][2] -= double(UpperLeftY);
481 K[0][2] -= double(UpperLeftX);
482 K[1][2] -= double(UpperLeftY);
483 PCutOut = K * PCutOut;
493 Texture.
SetROICorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
496 *Texture.
GetROI() = backupROI;
499 backupROI = *DenseDepthMap.
GetROI();
500 DenseDepthMap.
SetROICorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
503 *DenseDepthMap.
GetROI() = backupROI;
506 return GenerateDenseMesh(CutOutDenseDepthMap, PCutOut, CutOutTexture);
514 BIASWARN(
"Interpolation of texture coordinates not yet implemented !");
518 for (
unsigned int i = 0; i < 4; i++) {
538 meshVertices_.push_back(eucl);
539 textureCoords_.push_back(texcoord);
543 triangle.
Set(0, 1, 2);
544 triangleIndices_.push_back(triangle);
545 triangle.
Set(1, 2, 3);
546 triangleIndices_.push_back(triangle);
556 const double& opacity,
557 const double& resolution) {
560 if (resolution != 1.0)
561 newparams->
Rescale(
float(resolution));
563 BIASASSERT(opacity<=1.0)
564 unsigned int width = 0, height = 0;
568 for (
unsigned int y = 0; y < height; y++) {
569 for (
unsigned int x = 0; x < width; x++) {
582 R.SetFactor(resolution);
583 R.Filter(rectB, rect);
590 for (
unsigned int y = 0; y < rectAlpha.GetHeight(); y++) {
591 for (
unsigned int x = 0; x < rectAlpha.GetWidth(); x++) {
592 unsigned char *pD = &rect.GetImageDataArray()[y][3 * x];
593 unsigned char *pDA = &rectAlpha.GetImageDataArray()[y][4 * x];
597 *pDA++ = (
unsigned char) (255.0 * opacity);
601 GenerateDenseMesh(depthmap, Proj, rectAlpha, Proj);
611 std::vector<
Image<float> > & depthmaps,
float x,
float y,
612 float offset,
float minoffset,
double minCosAngle,
613 double maxDiagRatio,
bool simulateOnly) {
615 const int maxlayer = depthmaps.size() - 1;
616 int step = int(rint(log(offset) / log(2.0))) - 2;
627 unsigned int FoundDepthValues = 0;
630 for (c = 0; c < 5; c++) {
638 S[c][0] = x - offset;
639 S[c][1] = y - offset;
642 S[c][0] = x - offset;
643 S[c][1] = y + offset;
646 S[c][0] = x + offset;
647 S[c][1] = y + offset;
650 S[c][0] = x + offset;
651 S[c][1] = y - offset;
654 double depth = depthValues[int(S[c][1])][int(S[c][0])];
662 * depthValues[
int(S[c][1])][
int(S[c][0])]);
663 if (backProjected.
NormL2() < 1e-10) {
675 double diag2, diagratio;
677 bool passedMinAngleTest =
true;
682 if (FoundDepthValues == 5) {
685 (qp[1] - qp[0]).CrossProduct((qp[2] - qp[0]), normal[0]);
686 (qp[2] - qp[0]).CrossProduct((qp[3] - qp[0]), normal[1]);
687 (qp[3] - qp[0]).CrossProduct((qp[4] - qp[0]), normal[2]);
688 (qp[4] - qp[0]).CrossProduct((qp[1] - qp[0]), normal[3]);
689 for (
unsigned int i = 0; i < 4; i++) {
690 double mynorm = normal[i].
NormL2();
694 meannormal += normal[i];
706 for (
unsigned int c = 0; c < 6; c++) {
707 if (cosang[c] < minCosAngle)
711 diag1 = (qp[1] - qp[3]).NormL2();
712 diag2 = (qp[2] - qp[4]).NormL2();
713 diagratio = diag1 > diag2 ? diag1 / diag2 : diag2 / diag1;
714 if (diagratio > maxDiagRatio) {
717 LoS = qp[0] - P.
GetC();
719 if (GetAngle(meannormal, LoS) > maxAngle_) {
721 FoundDepthValues = 0;
723 if((!AcceptPolyCornerAngles(qp[0], qp[1], qp[2], minCornerAngle_)) ||
724 (!AcceptPolyCornerAngles(qp[0], qp[2], qp[3], minCornerAngle_)) ||
725 (!AcceptPolyCornerAngles(qp[0], qp[3], qp[4], minCornerAngle_)) ||
726 (!AcceptPolyCornerAngles(qp[0], qp[4], qp[1], minCornerAngle_))){
727 passedMinAngleTest =
false;
730 if(passedMinAngleTest){
731 if ((FoundDepthValues == 5) && ((!vetoed) || offset <= minoffset)) {
733 float newx, newy, newoff;
738 if ((newoff <= minoffset) && simulateOnly)
743 MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset, minCosAngle,
746 result &= MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset,
747 minCosAngle, maxDiagRatio,
true);
749 result &= MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset,
750 minCosAngle, maxDiagRatio,
true);
752 result &= MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset,
753 minCosAngle, maxDiagRatio,
true);
763 if (result || (newoff <= minoffset)) {
767 for (
unsigned int c = 1; c < 5; c++) {
778 unsigned int tw = Texture.
GetWidth();
781 thecoords[0] = float(uv[0]) / float(tw - 1);
782 thecoords[1] = 1.0f - float(uv[1]) / float(th - 1);
784 BIASWARNONCE(
"point does not project into texture!!!!");
788 for (
unsigned int f = 0; f < textureCoords_.size(); f++) {
789 if (textureCoords_[f][0] == thecoords[0] && textureCoords_[f][1] == thecoords[1]) {
796 indices.push_back(found);
798 meshVertices_.push_back(qp[c]);
799 textureCoords_.push_back(thecoords);
800 indices.push_back(currentIndex_++);
806 triangle.
Set(indices[0], indices[1], indices[2]);
807 triangleIndices_.push_back(triangle);
809 triangle.
Set(indices[2], indices[3], indices[0]);
810 triangleIndices_.push_back(triangle);
814 int x = int(S[0][0] - offset);
817 for (y =
int(S[0][1] - offset); y <= int(S[0][1] + offset); y++) {
823 if (depthmaps[0].IsPositionInImage(x, y))
824 for (
unsigned int i = 0; i < depthmaps.size(); i++) {
826 - Intersection).NormL2());
830 for (x =
int(S[0][0] - offset); x <= int(S[0][0] + offset); x++) {
836 if (depthmaps[0].IsPositionInImage(x, y))
837 for (
unsigned int i = 0; i < depthmaps.size(); i++) {
839 - Intersection).NormL2());
844 for (; y >= int(S[0][1] - offset); y--) {
850 if (depthmaps[0].IsPositionInImage(x, y))
851 for (
unsigned int i = 0; i < depthmaps.size(); i++) {
853 - Intersection).NormL2());
857 for (; x >= int(S[0][0] - offset); x--) {
863 if (depthmaps[0].IsPositionInImage(x, y))
864 for (
unsigned int i = 0; i < depthmaps.size(); i++) {
866 - Intersection).NormL2());
872 if (offset > (minoffset)) {
875 float newx, newy, newoff;
880 MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset, minCosAngle,
881 maxDiagRatio,
false);
883 MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset, minCosAngle,
884 maxDiagRatio,
false);
886 MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset, minCosAngle,
887 maxDiagRatio,
false);
889 MakeTriangles_(P, TexP, Texture, depthmaps, newx, newy, newoff, minoffset, minCosAngle,
890 maxDiagRatio,
false);
904 const unsigned int x0,
const unsigned int y0,
905 const unsigned int width,
const unsigned int height,
910 unsigned mwidth, mheight;
913 BIASASSERT(DenseDepthMap.
GetWidth()==mwidth &&
915 BIASASSERT(width==mwidth && height==mheight);
918 BIASASSERT(Texture.
GetWidth()==mwidth &&
927 bool straightlinesPreserved = (ppp != NULL);
930 straightlinesPreserved &= (!ppp->IsDistorted());
932 if (!straightlinesPreserved) {
933 BIASWARN(
"Your projection does not relate straight lines in the image to "
934 "straight lines in space, which leads to the problem that "
935 "the 3D triangle tesselation may contain holes, since it is done "
959 if (width <= 0 || height <= 0) {
960 BIASERR(
"tile width is too small!");
964 vector<Image<float> > depthimages;
966 int maxlevel = int(log(
double(DenseDepthMap.
GetWidth())) / log(2.0) - 3);
967 int spacing = int(pow(2.0, maxlevel));
968 cout <<
"maximum level is " << maxlevel <<
" spacing is " << spacing << endl;
969 depthimages.reserve(maxlevel + 1);
970 depthimages.push_back(DenseDepthMap);
973 bool smoothOriginal =
true;
974 if (smoothOriginal) {
976 depthimages.back().SetZero();
980 double curSigma = 0.5;
981 for (
int curLevel = 0; curLevel < maxlevel; curLevel++) {
982 double neededSigma = sqrt(pow(2.0,
double(2 * curLevel)) - curSigma * curSigma);
983 cout <<
"Filtering with sigma " << neededSigma << endl;
984 curSigma = pow(2.0,
double(curLevel));
986 depthimages.push_back(depthimages.back());
987 depthimages.back().SetZero();
989 depthimages.back(), 0.0f);
995 meshVertices_.clear();
996 vertexNormals_.clear();
997 textureCoords_.clear();
998 triangleIndices_.clear();
1000 meshVertices_.reserve(width * height);
1001 vertexNormals_.reserve(width * height);
1002 textureCoords_.reserve(width * height);
1003 triangleIndices_.reserve(width * height * 2);
1009 for (y = spacing + 1; y < height - spacing; y += spacing) {
1010 for (x = spacing + 1; x < width - spacing; x += spacing) {
1011 MakeTriangles_(P, TexP, Texture, depthimages,
float(x),
float(y),
float(spacing),
1012 float(minoffset), minCosAngle, maxDiagRatio,
false);
1016 bool multiPass =
true;
1018 for (
int curLevel = 2; curLevel < maxlevel; curLevel++) {
1019 cout <<
"pass " << curLevel <<
" of " << maxlevel - 1 <<
" ..." << flush << endl;
1020 meshVertices_.clear();
1021 vertexNormals_.clear();
1022 textureCoords_.clear();
1023 triangleIndices_.clear();
1026 for (y = spacing + 1; y < height - spacing; y += spacing) {
1027 for (x = spacing + 1; x < width - spacing; x += spacing) {
1028 MakeTriangles_(P, TexP, Texture, depthimages,
float(x),
float(y),
float(spacing),
1029 float(minoffset), minCosAngle, maxDiagRatio,
false);
1040 if (triangleIndices_.empty()) {
1041 BIASERR(
"no triangles generated");
1056 const bool doTexture = Texture.
GetWidth() > 0;
1057 const float w = Texture.
GetWidth() - 1.0f;
1058 const float h = Texture.
GetHeight() - 1.0f;
1060 meshVertices_.clear();
1061 vertexNormals_.clear();
1062 textureCoords_.clear();
1063 triangleIndices_.clear();
1065 meshVertices_.push_back(UL);
1066 meshVertices_.push_back(UR);
1067 meshVertices_.push_back(LL);
1068 meshVertices_.push_back(LR);
1070 const double normalLength = normal.
NormL2();
1072 for (
unsigned int i = 0; i < meshVertices_.size(); i++)
1073 vertexNormals_.push_back(normal);
1078 textureCoords_.push_back(
Vector2<float> ((
float) ul[0] / w, 1.0f - (
float) ul[1] / h));
1079 textureCoords_.push_back(
Vector2<float> ((
float) ur[0] / w, 1.0f - (
float) ur[1] / h));
1080 textureCoords_.push_back(
Vector2<float> ((
float) ll[0] / w, 1.0f - (
float) ll[1] / h));
1081 textureCoords_.push_back(
Vector2<float> ((
float) lr[0] / w, 1.0f - (
float) lr[1] / h));
1089 triangleIndices_.push_back(triangle);
1093 triangleIndices_.push_back(triangle);
1105 const float w = Texture.
GetWidth() - 1.0f;
1106 const float h = Texture.
GetHeight() - 1.0f;
1129 return GenerateTexturedQuad(Texture, UL, UR, LL, LR,
1140 const bool doTexture = Texture.
GetWidth() > 0;
1141 const float w = Texture.
GetWidth() - 1.0f;
1142 const float h = Texture.
GetHeight() - 1.0f;
1145 meshVertices_.clear();
1146 vertexNormals_.clear();
1147 textureCoords_.clear();
1148 triangleIndices_.clear();
1151 std::vector< Vector3<double> >::const_iterator x3d;
1152 for (x3d = X.begin(); x3d != X.end(); x3d++) {
1153 meshVertices_.push_back(*x3d);
1157 if (doTexture && !x.empty())
1159 BIASASSERT(X.size() == x.size());
1161 std::vector< Vector2<double> >::const_iterator x2d;
1162 for (x2d = x.begin(); x2d != x.end(); x2d++) {
1163 textureCoords_.push_back(
1164 Vector2<float>((
float)((*x2d)[0] / w), 1.0f - (
float)((*x2d)[1] / h)));
1169 const unsigned int num = X.size();
1171 for (
unsigned int idx = 0; idx+3 < num; idx += 2) {
1173 triangle[1] = idx + 1;
1174 triangle[2] = idx + 2;
1175 triangleIndices_.push_back(triangle);
1176 triangle[0] = idx + 1;
1177 triangle[1] = idx + 3;
1178 triangle[2] = idx + 2;
1179 triangleIndices_.push_back(triangle);
1191 std::vector< Vector2<double> > x;
1192 std::vector< Vector3<double> >::const_iterator x3d;
1193 x.reserve(X.size());
1195 for (x3d = X.begin(); x3d != X.end(); x3d++) {
1197 if (!
Equal(x2d[2], 0.0)) {
1207 return GenerateTexturedQuadStrip(Texture, X, x);
1224 vector<int> deletedVertices_;
1229 cout <<
"Mesh has " << meshVertices_.
size() <<
" vertices and " << triangleIndices_.size()
1230 <<
" triangles" << endl;
1232 std::vector<Quadric3> quadrics;
1233 std::vector<int> triangleIndicesRemove;
1236 for (
unsigned int i = 0; i < meshVertices_.size(); i++) {
1238 quadrics.push_back(quad);
1239 set<int> neighbours;
1240 neighboursOfVertex_.push_back(neighbours);
1242 vertexIsInTriangles_.push_back(tris);
1244 vertexIsInThisPairs_.push_back(pair);
1248 for (
unsigned int i = 0; i < triangleIndices_.size(); i++) {
1251 triangleIndicesRemove.push_back(0);
1254 neighboursOfVertex_[triangleIndices_[i][0]].insert(triangleIndices_[i][1]);
1255 neighboursOfVertex_[triangleIndices_[i][0]].insert(triangleIndices_[i][2]);
1258 neighboursOfVertex_[triangleIndices_[i][1]].insert(triangleIndices_[i][0]);
1259 neighboursOfVertex_[triangleIndices_[i][1]].insert(triangleIndices_[i][2]);
1262 neighboursOfVertex_[triangleIndices_[i][2]].insert(triangleIndices_[i][0]);
1263 neighboursOfVertex_[triangleIndices_[i][2]].insert(triangleIndices_[i][1]);
1266 vertexIsInTriangles_[triangleIndices_[i][0]].insert(i);
1267 vertexIsInTriangles_[triangleIndices_[i][1]].insert(i);
1268 vertexIsInTriangles_[triangleIndices_[i][2]].insert(i);
1277 area = ThreePointsToPlane_(v1, v2, v3, test);
1279 Quadric3 Q(test[0], test[1], test[2], test[3], area);
1282 quadrics[triangleIndices_[i][0]] += Q;
1283 quadrics[triangleIndices_[i][1]] += Q;
1284 quadrics[triangleIndices_[i][2]] += Q;
1288 set<int>::iterator externIter, internIter;
1289 for (
unsigned int i = 0; i < neighboursOfVertex_.size(); i++) {
1290 for (externIter = neighboursOfVertex_[i].begin(); externIter
1291 != neighboursOfVertex_[i].end(); ++externIter) {
1293 if ((
unsigned int)*externIter > i) {
1296 e.
IDv2 = *externIter;
1298 validPairs_.push_back(e);
1299 vertexIsInThisPairs_[e.
IDv1].insert(validPairs_.size() - 1);
1300 vertexIsInThisPairs_[e.
IDv2].insert(validPairs_.size() - 1);
1304 #ifdef USE_BOUNDARY_TEST
1307 int countTriangles = 0;
1309 for (internIter = vertexIsInTriangles_[e.
IDv1].begin(); internIter
1310 != vertexIsInTriangles_[e.
IDv1].end(); ++internIter) {
1311 if ((triangleIndices_[*internIter][0] == e.
IDv2) || (triangleIndices_[*internIter][1]
1312 == e.
IDv2) || (triangleIndices_[*internIter][2] == e.
IDv2)) {
1314 triangleID = *internIter;
1320 if (countTriangles == 1) {
1323 ThreePointsToPlane_(meshVertices_[triangleIndices_[triangleID][0]],
1324 meshVertices_[triangleIndices_[triangleID][1]],
1325 meshVertices_[triangleIndices_[triangleID][2]], test);
1330 area2 = ThreePointsToPlane_(meshVertices_[e.
IDv1], meshVertices_[e.
IDv2], normale,
1335 Quadric3 Q2(senkrechteEbene[0], senkrechteEbene[1], senkrechteEbene[2],
1336 senkrechteEbene[3], area2);
1339 quadrics[e.
IDv1] += Q2;
1340 quadrics[e.
IDv2] += Q2;
1374 for (
unsigned int i = 0; i < validPairs_.size(); i++) {
1376 Q = quadrics[validPairs_[i].IDv1];
1377 Q += quadrics[validPairs_[i].IDv2];
1380 #ifdef USE_OPTIMIZED
1382 if (Q.
Optimize(validPairs_[i].newV)) {
1383 validPairs_[i].err = Q.
Evaluate(validPairs_[i].newV[0], validPairs_[i].newV[1],
1384 validPairs_[i].newV[2]);
1392 double ei = Q.
Evaluate(vi[0], vi[1], vi[2]);
1393 double ej = Q.
Evaluate(vj[0], vj[1], vj[2]);
1396 validPairs_[i].err = ei;
1397 validPairs_[i].newV = vi;
1399 validPairs_[i].err = ej;
1400 validPairs_[i].newV = vj;
1402 #ifdef USE_OPTIMIZED
1408 #ifdef USE_CONTRACTION_TEST
1409 TestContraction(validPairs_[i].IDv1, validPairs_[i].IDv2, i,
true);
1413 sorted.insert(validPairs_[i]);
1417 std::multiset<Edge,Edge>::iterator iter;
1420 int valid_triangles = triangleIndices_.size();
1421 int target = int(valid_triangles * (reduce/100.0));
1426 std::vector<int> dead_triangles;
1427 std::vector<int> moved_triangles;
1428 std::vector<BIAS::Vector<int> > trianglesToKill;
1429 std::vector<int> IntegerToKill;
1433 cout <<
"starting mesh reduction... " << endl;
1435 int difference = valid_triangles - target;
1437 int lastPerCent = 0;
1438 while (valid_triangles > target && sorted.size() > 0) {
1440 progress = (int)rint((
double) 1 - ((double) (valid_triangles - target)
1441 / (double) difference)) * 100;
1443 if (progress % 10 == 0) {
1444 if (progress != lastPerCent) {
1445 cout << progress <<
" %" << endl;
1446 lastPerCent = progress;
1451 iter = sorted.begin();
1456 dead_triangles.clear();
1457 moved_triangles.clear();
1467 GetNeighbours_(ed.
IDv1, ed.
IDv2, dead_triangles, moved_triangles, moved_pivot);
1470 quadrics[ed.
IDv1] += quadrics[ed.
IDv2];
1472 vector<Edge> maybeDoubleEdges;
1477 IntegerToKill.clear();
1478 set<int>::iterator pairIter;
1479 for (pairIter = vertexIsInThisPairs_[ed.
IDv1].begin(); pairIter
1480 != vertexIsInThisPairs_[ed.
IDv1].end(); ++pairIter) {
1482 sorted.erase(validPairs_[*pairIter]);
1484 if (validPairs_[*pairIter].IDv1 == ed.
IDv2 || validPairs_[*pairIter].IDv2 == ed.
IDv2) {
1486 IntegerToKill.push_back(*pairIter);
1489 maybeDoubleEdges.push_back(validPairs_[*pairIter]);
1493 for(
unsigned int j = 0; j < IntegerToKill.size(); j++){
1494 vertexIsInThisPairs_[ed.
IDv1].erase(IntegerToKill[j]);
1495 vertexIsInThisPairs_[ed.
IDv2].erase(IntegerToKill[j]);
1497 IntegerToKill.clear();
1500 for (pairIter = vertexIsInThisPairs_[ed.
IDv2].begin(); pairIter
1501 != vertexIsInThisPairs_[ed.
IDv2].end(); ++pairIter) {
1503 Edge edg = validPairs_[*pairIter];
1505 if (validPairs_[*pairIter].IDv1 == ed.
IDv2) {
1506 sorted.erase(validPairs_[*pairIter]);
1507 for (
unsigned int j = 0; j < maybeDoubleEdges.size(); j++) {
1509 if(maybeDoubleEdges[j].IDv1 == validPairs_[*pairIter].IDv2)
1511 else if(maybeDoubleEdges[j].IDv2 == validPairs_[*pairIter].IDv2)
1513 else if(validPairs_[*pairIter].IDv2 == ed.
IDv1)
1519 if(validPairs_[*pairIter].IDv2 == ed.
IDv1){
1520 IntegerToKill.push_back(*pairIter);
1522 validPairs_[*pairIter].IDv1 = ed.
IDv1;
1523 vertexIsInThisPairs_[ed.
IDv1].insert(*pairIter);
1526 IntegerToKill.push_back(*pairIter);
1531 if (validPairs_[*pairIter].IDv2 == ed.
IDv2) {
1532 sorted.erase(validPairs_[*pairIter]);
1533 for (
unsigned int j = 0; j < maybeDoubleEdges.size(); j++) {
1535 if(maybeDoubleEdges[j].IDv1 == validPairs_[*pairIter].IDv1)
1537 else if(maybeDoubleEdges[j].IDv2 == validPairs_[*pairIter].IDv1)
1539 else if(validPairs_[*pairIter].IDv1 == ed.
IDv1)
1544 if(validPairs_[*pairIter].IDv1 == ed.
IDv1){
1545 IntegerToKill.push_back(*pairIter);
1547 validPairs_[*pairIter].IDv2 = ed.
IDv1;
1548 vertexIsInThisPairs_[ed.
IDv1].insert(*pairIter);
1551 IntegerToKill.push_back(*pairIter);
1557 for(
unsigned int j = 0; j < IntegerToKill.size(); j++){
1558 vertexIsInThisPairs_[validPairs_[IntegerToKill[j]].IDv1].erase(IntegerToKill[j]);
1559 vertexIsInThisPairs_[validPairs_[IntegerToKill[j]].IDv2].erase(IntegerToKill[j]);
1564 meshVertices_[ed.
IDv1] += dv1;
1572 unsigned int tw = Texture.
GetWidth();
1576 double u = uv[0] / float(tw - 1);
1577 double v = 1 - uv[1] / float(th - 1);
1578 texCoord.
Set(
float(u),
float(v));
1580 textureCoords_[ed.
IDv1] = texCoord;
1585 set<int>::iterator listIter;
1587 for (
unsigned int i = 0; i < moved_triangles.size(); i++) {
1588 if (triangleIndices_[moved_triangles[i]][0] == ed.
IDv2) {
1589 triangleIndices_[moved_triangles[i]][0] = ed.
IDv1;
1590 vertexIsInTriangles_[ed.
IDv1].insert(moved_triangles[i]);
1593 if (triangleIndices_[moved_triangles[i]][1] == ed.
IDv2) {
1594 triangleIndices_[moved_triangles[i]][1] = ed.
IDv1;
1595 vertexIsInTriangles_[ed.
IDv1].insert(moved_triangles[i]);
1597 if (triangleIndices_[moved_triangles[i]][2] == ed.
IDv2) {
1598 triangleIndices_[moved_triangles[i]][2] = ed.
IDv1;
1599 vertexIsInTriangles_[ed.
IDv1].insert(moved_triangles[i]);
1604 for (
unsigned int i = 0; i < dead_triangles.size(); i++) {
1606 vertexIsInTriangles_[triangleIndices_[dead_triangles[i]][0]].erase(dead_triangles[i]);
1607 vertexIsInTriangles_[triangleIndices_[dead_triangles[i]][1]].erase(dead_triangles[i]);
1608 vertexIsInTriangles_[triangleIndices_[dead_triangles[i]][2]].erase(dead_triangles[i]);
1610 triangleIndicesRemove[dead_triangles[i]] = 1;
1614 vertexIsInTriangles_[ed.
IDv2].clear();
1615 vertexIsInThisPairs_[ed.
IDv2].clear();
1618 valid_triangles -= dead_triangles.size();
1621 for (pairIter = vertexIsInThisPairs_[ed.
IDv1].begin(); pairIter
1622 != vertexIsInThisPairs_[ed.
IDv1].end(); ++pairIter) {
1624 sorted.erase(validPairs_[*pairIter]);
1626 int doubleV1p = validPairs_[*pairIter].IDv1;
1627 int doubleV2p = validPairs_[*pairIter].IDv2;
1629 if(doubleV1p == doubleV2p)
1630 cout <<
"SOMETHING WENT WRONG" << endl;
1633 Q = quadrics[validPairs_[*pairIter].IDv1];
1634 Q += quadrics[validPairs_[*pairIter].IDv2];
1635 #ifdef USE_OPTIMIZED
1637 if (Q.
Optimize(validPairs_[*pairIter].newV)) {
1638 validPairs_[*pairIter].err = Q.
Evaluate(validPairs_[*pairIter].newV[0],
1639 validPairs_[*pairIter].newV[1],
1640 validPairs_[*pairIter].newV[2]);
1646 double ei = Q.
Evaluate(vi[0], vi[1], vi[2]);
1647 double ej = Q.
Evaluate(vj[0], vj[1], vj[2]);
1650 validPairs_[*pairIter].err = ei;
1651 validPairs_[*pairIter].newV = vi;
1653 validPairs_[*pairIter].err = ej;
1654 validPairs_[*pairIter].newV = vj;
1656 #ifdef USE_OPTIMIZED
1661 #ifdef USE_CONTRACTION_TEST
1662 TestContraction(ed.
IDv1, ed.
IDv2, *pairIter,
true);
1665 sorted.insert(validPairs_[*pairIter]);
1669 cout <<
"100 %" << endl;
1672 std::vector<BIAS::Vector<int> > tmp;
1674 for(
unsigned int i = 0; i < triangleIndices_.size(); i++){
1675 if(triangleIndicesRemove[i] == 0){
1676 tmp.push_back(triangleIndices_[i]);
1680 triangleIndices_.clear();
1681 triangleIndices_ = tmp;
1683 cout <<
"Triangles after mesh reduction: " << triangleIndices_.size() << endl;
1721 return (N.
NormL2() * 0.5);
1729 std::vector<int>& moved_triangles,
int &moved_pivot) {
1731 multiset<int> neighbours;
1732 set<int>::iterator iter;
1735 for (iter = vertexIsInTriangles_[v1].begin(); iter != vertexIsInTriangles_[v1].end(); ++iter) {
1736 neighbours.insert(*iter);
1741 for (iter = vertexIsInTriangles_[v2].begin(); iter != vertexIsInTriangles_[v2].end(); ++iter) {
1742 neighbours.insert(*iter);
1744 if (neighbours.count(*iter) == 1) {
1745 moved_triangles.push_back(*iter);
1748 dead_triangles.push_back(*iter);
1769 set<int>::iterator iter;
1771 for (iter = vertexIsInTriangles_[v1].begin();
1772 iter != vertexIsInTriangles_[v1].end();
1775 if (triangleIndices_[*iter][0] != v2 && triangleIndices_[*iter][1] != v2
1776 && triangleIndices_[*iter][2] != v2) {
1780 normalOld = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1781 meshVertices_[triangleIndices_[*iter][1]],
1782 meshVertices_[triangleIndices_[*iter][2]]);
1784 if (triangleIndices_[*iter][0] == v1)
1785 normalNew = GetPlaneNormalEuclidean(validPairs_[edge].newV,
1786 meshVertices_[triangleIndices_[*iter][1]],
1787 meshVertices_[triangleIndices_[*iter][2]]);
1788 if (triangleIndices_[*iter][1] == v1)
1789 normalNew = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1790 validPairs_[edge].newV,
1791 meshVertices_[triangleIndices_[*iter][2]]);
1792 if (triangleIndices_[*iter][2] == v1)
1793 normalNew = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1794 meshVertices_[triangleIndices_[*iter][1]],
1795 validPairs_[edge].newV);
1798 if (normalNew.
NormL2() > std::numeric_limits<double>::epsilon()
1799 && normalOld.
NormL2() > std::numeric_limits<double>::epsilon()) {
1800 const double angle = GetAngle(normalOld, normalNew);
1801 if (angle > 0.15 || angle < -0.15) {
1802 validPairs_[edge].err *= 1000;
1810 for (iter = vertexIsInTriangles_[v2].begin();
1811 iter != vertexIsInTriangles_[v2].end();
1814 if (triangleIndices_[*iter][0] != v1 && triangleIndices_[*iter][1] != v1
1815 && triangleIndices_[*iter][2] != v1) {
1819 normalOld = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1820 meshVertices_[triangleIndices_[*iter][1]],
1821 meshVertices_[triangleIndices_[*iter][2]]);
1823 if (triangleIndices_[*iter][0] == v2)
1824 normalNew = GetPlaneNormalEuclidean(validPairs_[edge].newV,
1825 meshVertices_[triangleIndices_[*iter][1]],
1826 meshVertices_[triangleIndices_[*iter][2]]);
1827 if (triangleIndices_[*iter][1] == v2)
1828 normalNew = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1829 validPairs_[edge].newV,
1830 meshVertices_[triangleIndices_[*iter][2]]);
1831 if (triangleIndices_[*iter][2] == v2)
1832 normalNew = GetPlaneNormalEuclidean(meshVertices_[triangleIndices_[*iter][0]],
1833 meshVertices_[triangleIndices_[*iter][1]],
1834 validPairs_[edge].newV);
1837 if (normalNew.
NormL2() > std::numeric_limits<double>::epsilon()
1838 && normalOld.
NormL2() > std::numeric_limits<double>::epsilon()) {
1839 const double angle = GetAngle(normalOld, normalNew);
1841 if (angle > 0.15 || angle < -0.15) {
1842 validPairs_[edge].err *= 1000;
1858 vector<vector<size_t> > pointsToTris(meshVertices_.size());
1860 for (
size_t triCnt = 0; triCnt < triangleIndices_.size(); ++triCnt) {
1861 for (
size_t cornerCnt = 0;
1862 cornerCnt < size_t(triangleIndices_[triCnt].size());
1864 pointsToTris[triangleIndices_[triCnt][cornerCnt]].push_back(triCnt);
1871 vector<vector<size_t> > segments(triangleIndices_.size());
1872 size_t emptySegmentIndex = 0;
1873 vector<int> trisToSegments(triangleIndices_.size(), -1);
1877 for (
size_t pointCnt = 0; pointCnt < pointsToTris.size(); ++pointCnt) {
1879 if (pointsToTris[pointCnt].empty()) {
1880 BIASWARN(
"mesh contains a vertex that is not used by any triangle")
1888 const size_t firstTriIndex = pointsToTris[pointCnt][0];
1889 int segmentForCurPoint = trisToSegments[firstTriIndex];
1891 if (segmentForCurPoint < 0) {
1892 segments[emptySegmentIndex].push_back(firstTriIndex);
1893 trisToSegments[firstTriIndex] = emptySegmentIndex;
1894 segmentForCurPoint = (int)emptySegmentIndex;
1895 ++emptySegmentIndex;
1899 for (
size_t triCnt = 1; triCnt < pointsToTris[pointCnt].size(); ++triCnt) {
1900 const size_t curTriIndex = pointsToTris[pointCnt][triCnt];
1901 const int curTriSegment = trisToSegments[curTriIndex];
1904 if (curTriSegment < 0) {
1905 segments[segmentForCurPoint].push_back(curTriIndex);
1906 trisToSegments[curTriIndex] = segmentForCurPoint;
1908 else if (curTriSegment == segmentForCurPoint) {
1912 for (
size_t triSegmCnt = 0;
1913 triSegmCnt < segments[size_t(curTriSegment)].size();
1915 segments[segmentForCurPoint].push_back(segments[
size_t(curTriSegment)][triSegmCnt]);
1916 trisToSegments[segments[size_t(curTriSegment)][triSegmCnt]]
1917 = segmentForCurPoint;
1920 segments[size_t(curTriSegment)].clear();
1928 size_t maxNumTris = 0;
1929 int biggestSegmentIndex = -1;
1931 for (
size_t segmCnt = 0; segmCnt < segments.size(); ++segmCnt) {
1932 if (segments[segmCnt].size() > maxNumTris) {
1933 maxNumTris = segments[segmCnt].size();
1934 biggestSegmentIndex = int(segmCnt);
1938 if (biggestSegmentIndex == -1) {
1939 BIASWARN(
"did not find any connected segments at all")
1946 vector<Vector3<double> > vertices;
1947 vector<Vector3<double> > normals;
1948 vector<Vector4<unsigned char> > colors;
1949 vector<int> newVertexIndices(meshVertices_.size(), -1);
1951 for (
size_t triCnt = 0;
1952 triCnt < segments[biggestSegmentIndex].size();
1954 const size_t curTriIndex = segments[biggestSegmentIndex][triCnt];
1956 for (
size_t pointCnt = 0;
1957 pointCnt < size_t(triangleIndices_[curTriIndex].size());
1959 const size_t curPointIndex = triangleIndices_[curTriIndex][pointCnt];
1961 if (newVertexIndices[curPointIndex] == -1) {
1962 newVertexIndices[curPointIndex] = vertices.size();
1963 vertices.push_back(meshVertices_[curPointIndex]);
1964 if (!vertexNormals_.empty()) {
1965 normals.push_back(vertexNormals_[curPointIndex]);
1967 colors.push_back(vertexColors_[curPointIndex]);
1972 vector<Vector<int> > triangleIndices;
1973 triangleIndices.reserve(segments[biggestSegmentIndex].size());
1975 for (
size_t triCnt = 0;
1976 triCnt < segments[biggestSegmentIndex].size();
1979 = triangleIndices_[segments[biggestSegmentIndex][triCnt]];
1980 Vector<int> newTri(triangleIndices_[segments[biggestSegmentIndex][triCnt]].size());
1982 for (
size_t pointCnt = 0; pointCnt < size_t(origTri.
size()); ++pointCnt) {
1983 const size_t origIndex = origTri[pointCnt];
1984 const size_t newIndex = newVertexIndices[origIndex];
1985 newTri[pointCnt] = newIndex;
1988 triangleIndices.push_back(newTri);
1991 biggestSegment.
SetMesh(vertices, normals, colors, triangleIndices);
1998 if (meshVertices_.empty()) {
1999 minPoint.
Set(0.0, 0.0, 0.0);
2000 maxPoint.
Set(0.0, 0.0, 0.0);
2006 minPoint.
Set(numeric_limits<double>::max(),
2007 numeric_limits<double>::max(),
2008 numeric_limits<double>::max());
2009 maxPoint.
Set(-numeric_limits<double>::max(),
2010 -numeric_limits<double>::max(),
2011 -numeric_limits<double>::max());
2013 for (
size_t vertexCnt = 0; vertexCnt < meshVertices_.size(); ++vertexCnt) {
2016 if (curVertex[0] < minPoint[0]) minPoint[0] = curVertex[0];
2017 if (curVertex[1] < minPoint[1]) minPoint[1] = curVertex[1];
2018 if (curVertex[2] < minPoint[2]) minPoint[2] = curVertex[2];
2020 if (curVertex[0] > maxPoint[0]) maxPoint[0] = curVertex[0];
2021 if (curVertex[1] > maxPoint[1]) maxPoint[1] = curVertex[1];
2022 if (curVertex[2] > maxPoint[2]) maxPoint[2] = curVertex[2];
2029 BIASASSERT(normalForUnusedVertices.
NormL2() == 1.0)
2032 vertexNormals_.clear();
2033 vertexNormals_.resize(meshVertices_.size(), normalForUnusedVertices);
2036 vector<Vector3<double> > triNormals;
2037 triNormals.reserve(triangleIndices_.size());
2039 for (
size_t triCnt = 0; triCnt < triangleIndices_.size(); ++triCnt) {
2041 const Vector3<double>& p1 = meshVertices_[triangleIndices_[triCnt][0]];
2042 const Vector3<double>& p2 = meshVertices_[triangleIndices_[triCnt][1]];
2043 const Vector3<double>& p3 = meshVertices_[triangleIndices_[triCnt][2]];
2054 triNormals.push_back(triNormal);
2062 triNormals.push_back(triNormal);
2068 vector<vector<int> > trianglesForVertices(meshVertices_.size());
2070 for (
size_t triCnt = 0; triCnt < triangleIndices_.size(); ++triCnt) {
2071 trianglesForVertices[triangleIndices_[triCnt][0]].push_back(triCnt);
2072 trianglesForVertices[triangleIndices_[triCnt][1]].push_back(triCnt);
2073 trianglesForVertices[triangleIndices_[triCnt][2]].push_back(triCnt);
2078 for (
size_t vertexCnt = 0;
2079 vertexCnt < trianglesForVertices.size();
2081 if (!trianglesForVertices[vertexCnt].empty()) {
2082 vertexNormals_[vertexCnt].Set(0.0, 0.0, 0.0);
2084 for (
size_t triCnt = 0;
2085 triCnt < trianglesForVertices[vertexCnt].size();
2087 vertexNormals_[vertexCnt]
2088 += triNormals[trianglesForVertices[vertexCnt][triCnt]];
2091 vertexNormals_[vertexCnt]
2092 /= double(trianglesForVertices[vertexCnt].size());
2093 vertexNormals_[vertexCnt].Normalize();
int GetCopyOfROI(ImageBase ©) const
returns a copy of ROI (a new image) lower right point excluded, only interleaved images ! ...
virtual BIAS::Vector3< double > GetC() const
Get projection center.
void SetFromPoints(const HomgPoint3D &p1, const HomgPoint3D &p2, const HomgPoint3D &p3)
constructs a homogeneous plane from three points
void GetEuclidean(Vector3< HOMGPOINT3D_TYPE > &dest) const
calculate affine coordinates of this and write them to dest affine coordinates are projective coordin...
class for handling different region of interest (ROI) representations...
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this->data_
int GenerateDenseMesh(const BIAS::Image< float > &DenseDepthMap, const BIAS::Image< unsigned char > &Texture)
Calculate a triangle mesh from dense depth map without PMatrix.
TriangleMesh(const double &minCornerAngle=M_PI *5.0/180.0, const double &maxAngle=M_PI *60.0/180.0, const double depthScale=1.0)
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
int GetLineIntersection(const HomgPoint3D &PointOnLine, const HomgPoint3D &LineDir, HomgPoint3D &Intersection) const
compute the intersection point of the plane with a line (defined by point and direction) ...
void GenerateTexturedCamera(const ProjectionParametersBase *PPB, Image< unsigned char > &rgbtexture, const double &scale=1.0, const double &opacity=1.0, const double &resolution=1.0)
generates the sensor plane / cylinder / sphere in 3D space
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
int ChangeTexture(const BIAS::Image< unsigned char > &texture)
Replace the texture of this mesh.
int GenerateImagePlane(const BIAS::Projection &P, const BIAS::Image< unsigned char > &Texture, const double &w=1.0)
backproject image onto a plane in space so far only implemented for perspective cameras ...
double NormL2() const
Return the L2 norm: sqrt(a^1 + a^2 + ...)
bool Optimize(Vector3< double > &v)
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
const unsigned int size() const
virtual HomgPoint3D UnProjectToPoint(const HomgPoint2D &pos, double depth, bool IgnoreDistortion=false) const
calculates a 3D point in the global (not the rig) coordinate system, which belongs to the image posit...
int Filter7x7GreyIgnoreBelowThreshold(const Image< InputStorageType > &src, Image< OutputStorageType > &dst, const InputStorageType &thresh)
7x7 gauss filtering, values below threshold are ignored useful for depth map filtering ...
void ScalarProduct(const Vector3< T > &argvec, T &result) const
scalar product (=inner product) of two vectors, storing the result in result
virtual void SetImageSize(const unsigned int w, const unsigned int h)
Set image dimensions (in pixels).
virtual ProjectionParametersBase * Clone() const =0
Covariant virtual copy constructor used in BIAS::Projection.
virtual void Rescale(double ratio, const double offset=0.0)
Adapt internal parameters to resampled image.
void SetColorModel(EColorModel Model)
void GetEuclidean(Vector2< HOMGPOINT2D_TYPE > &dest) const
calculate affine coordinates of this and write them to dest affine coordinates are projective coordin...
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
void GetBiggestConnectedSegment(TriangleMesh &biggestSegment) const
Returns the biggest connected segment of this triangle mesh.
bool MakeTriangles_(const Projection &P, const Projection &TexP, const BIAS::Image< unsigned char > &Texture, std::vector< Image< float > > &depthmaps, float x, float y, float offset, float minoffset, double minCosAngle, double maxDiagRatio, bool simulateOnly)
BIAS::Vector3< T > GetNormalized() const
return a normalized vector of this
virtual void SetP(const PMatrix &P)
set from P
int GetR(Matrix3x3< double > &R)
double Evaluate(double x, double y, double z)
unsigned int GetWidth() const
void SetZero()
equivalent to matrix call
double NormL2() const
Return the L2 norm: sqrt(a^2 + b^2 + c^2 + d^2)
void TestContraction(int v1, int v2, int edge, bool init=false)
Tests if a triangle that is involved in the contraction changes direction or overlapps.
Struct for easier handling of edges.
void GenerateVertexNormals(bool leftHanded=true, Vector3< double > normalForUnusedVertices=Vector3< double >(-1.0, 0.0, 0.0))
Computes the normals for the vertices by averaging the normals of adjacent triangles.
class Vector4 contains a Vector of dim.
void SetMesh(BIAS::Image< unsigned char > texture, std::vector< BIAS::Vector3< double > > meshVertices, std::vector< BIAS::Vector3< double > > vertexNormals, std::vector< BIAS::Vector2< float > > textureCoords, std::vector< BIAS::Vector< int > > triangleIndices)
void Set(const T &scalar)
set all elements to a scalar value
void CrossProduct(const Vector3< T > &argvec, Vector3< T > &destvec) const
cross product of two vectors destvec = this x argvec
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
ROI * GetROI()
Returns a pointer to the roi object.
void UnProjectToRay(const HomgPoint2D &pos, Vector3< double > &origin, Vector3< double > &rayDir, unsigned int cam=0, bool IgnoreDistortion=false) const
calculates the viewing ray in the global coordinate frame (not the rig) from the camera center which ...
This class hides the underlying projection model, like projection matrix, spherical camera...
void AddIP(const T &scalar)
Addition (in place) of an scalar.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Create and represent a 3D triangle mesh.
void SetParams(const double &minCornerAngle=M_PI *5.0/180.0, const double &maxAngle=M_PI *60.0/180.0, const double depthScale=1.0)
void InvalidateDecomposition()
to re-Decompose_() after filling with data use this.
unsigned int GetHeight() const
void SetSigma(const double si)
int GenerateTexturedQuad(const Image< unsigned char > &Texture, const Vector3< double > &UL, const Vector3< double > &UR, const Vector3< double > &LL, const Vector3< double > &LR, const Vector2< double > &ul, const Vector2< double > &ur, const Vector2< double > &ll, const Vector2< double > &lr, const Vector3< double > &normal=Vector3< double >(0, 0, 0))
Generate planar quad in 3D space with given texture coordinates.
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same "size" as Image of other type
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
virtual bool DoesPointProjectIntoImage(const BIAS::HomgPoint3D &X, BIAS::HomgPoint2D &x, unsigned int cam=0, bool IgnoreDistortion=false) const
Checks if 3D point projects into specified image and returns belonging 2D image point.
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
bool Equal(const T left, const T right, const T eps)
comparison function for floating point values See http://www.boost.org/libs/test/doc/components/test_...
RGBA, 4 channels, order: red,green,blue,alpha.
void Sub(const T &scalar, Vector3< T > &dest) const
Substraction with a scalar, storing results in destination vector.
int GetC(Vector3< double > &C)
computes translation vector origin world coo -> origin camera coo (center), uses decomposition, which is cached
Vector3< double > UnProjectToPoint(const HomgPoint2D &pos, double depth, unsigned int cam=0, bool IgnoreDistortion=false) const
calculates a 3D point in the global (not the rig) coordinate system, which belongs to the image posit...
bool SimplifyMeshSurface_(const BIAS::Image< unsigned char > &Texture, BIAS::Projection &TexP, double reduceValue)
Simplifies a TriangleMesh to a desired percentage of triangles of the original mesh.
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
void GetNeighbours_(int v1, int v2, std::vector< int > &dead_triangles, std::vector< int > &moved_triangles, int &moved_pivot)
get the neighbours of the contracted points and returns two list that contains the triangles to remov...
int GenerateSimplifiedMesh(const Image< float > &DenseDepthMap, const Projection &P, const Image< unsigned char > &Texture, const unsigned int x0, const unsigned int y0, const unsigned int width, const unsigned int height, double minCosAngle=0.8, double maxDiagRatio=3.0)
Implements a 3D quadric and quadric operations.
describes a projective 3D -> 2D mapping in homogenous coordinates
double NormFrobenius() const
Return Frobenius norm = sqrt(trace(A^t * A)).
virtual HomgPoint2D Project(const HomgPoint3D &X, unsigned int cam=0, bool IgnoreDistortion=false) const
returns the 2d projection of X in camera cam, where X is given in the global coordinate frame (not th...
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
int GenerateTexturedQuadStrip(const Image< unsigned char > &Texture, const std::vector< Vector3< double > > &X, const std::vector< Vector2< double > > &x)
Generate a strip of planar quads in 3D space using the given texture coordinates. ...
int SetROICorners(unsigned int UpperLeftX, unsigned int UpperLeftY, unsigned int LowerRightX, unsigned int LowerRightY)
void GetBoundingBox(Vector3< double > &minPoint, Vector3< double > &maxPoint) const
Returns the minimal and maximal point of the axis-aligned bounding box of this triangle mesh...
void Set(const HOMGPOINT2D_TYPE &x, const HOMGPOINT2D_TYPE &y)
set elementwise with given 2 euclidean scalar values.
Vector3< double > GetC(unsigned int cam=0) const
return Center of camera with index cam.
double ThreePointsToPlane_(Vector3< double > v1, Vector3< double > v2, Vector3< double > v3, Vector4< double > &erg)
calculates a plan of three points and returns it area
Vector3< T > & Normalize()
normalize this vector to length 1
void SetZero()
zeroes the image
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
class BIASGeometryBase_EXPORT HomgPoint2D
void Compose(const Matrix3x3< double > &K, const Matrix3x3< double > &R, const Vector3< double > &C)
composes this from K, R and C using P = [ K R' | -K R' C ] with R' = transpose(R) ...
virtual HomgPoint3D UnProjectToImagePlane(const HomgPoint2D &pos, const double &depth=1.0, bool IgnoreDistortion=false) const =0
map points from image onto unit diameter image plane in 3D.
class BIASGeometryBase_EXPORT HomgPoint3D
int GetK(KMatrix &K)
calibration matrix
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
A homogeneous plane (in P^3) All points X on the plane p fulfill p ' * X = 0.