Skip to content

Commit 268b530

Browse files
committed
ptm has least square fitting for rank deficient matrix
1 parent eace67c commit 268b530

File tree

3 files changed

+49
-43
lines changed

3 files changed

+49
-43
lines changed

relight-cli/rtibuilder.cpp

+45-40
Original file line numberDiff line numberDiff line change
@@ -398,48 +398,47 @@ MaterialBuilder RtiBuilder::pickBasePTM(std::vector<Vector3f> &lights) {
398398
x = (At * A)^-1*At*b
399399
*/
400400

401-
uint32_t dim = ndimensions*3;
401+
uint32_t nlights = lights.size();
402+
uint32_t dim = nlights*3; //number of lights *3
402403
MaterialBuilder mat;
403404
mat.mean.resize(dim, 0.0);
404405

405-
Eigen::MatrixXf A(lights.size(), 6);
406-
for(uint32_t l = 0; l < lights.size(); l++) {
406+
bool first_degree = (colorspace == LRGB && nplanes == 6) || (colorspace == RGB && nplanes == 9);
407+
408+
Eigen::MatrixXf A(lights.size(), first_degree ? 3 : 6);
409+
for(uint32_t l = 0; l < nlights; l++) {
407410
Vector3f &light = lights[l];
408411
A(l, 0) = 1.0;
409412
A(l, 1) = light[0];
410413
A(l, 2) = light[1];
411-
A(l, 3) = light[0]*light[0];
412-
A(l, 4) = light[0]*light[1];
413-
A(l, 5) = light[1]*light[1];
414-
}
415-
416-
if((colorspace == LRGB && nplanes == 6) || (colorspace == RGB && nplanes == 9)) {
417-
A.conservativeResize(lights.size(), 3);
414+
if(!first_degree) {
415+
A(l, 3) = light[0]*light[0];
416+
A(l, 4) = light[0]*light[1];
417+
A(l, 5) = light[1]*light[1];
418+
}
418419
}
419420

420421
Eigen::MatrixXf iA = (A.transpose()*A).inverse()*A.transpose();
421422
if(iA.hasNaN()) {
422-
Eigen::MatrixXf AN(lights.size(), nplanes);
423-
for(uint32_t l = 0; l < lights.size(); l++) {
424-
Vector3f &light = lights[l];
425-
if(colorspace == LRGB) {
426-
A(l, 0) = 1.0;
427-
A(l, 1) = light[0];
428-
A(l, 2) = light[1];
429-
check for number of planes
430-
A(l, 3) = light[0]*light[0];
431-
A(l, 4) = light[0]*light[1];
432-
A(l, 5) = light[1]*light[1];
433-
} else {
434-
A(l, 0) = 1.0;
435-
A(l, 1) = light[0];
436-
A(l, 2) = light[1];
437-
A(l, 3) = light[0]*light[0];
438-
A(l, 4) = light[0]*light[1];
439-
A(l, 5) = light[1]*light[1];
423+
if(colorspace != LRGB) {
424+
A = Eigen::MatrixXf::Zero(nlights*3, nplanes);
425+
426+
for(uint32_t l = 0; l < lights.size(); l++) {
427+
Vector3f &light = lights[l];
428+
for(int k = 0; k < 3; k++) {
429+
A(l*3+k, 0*3+k) = 1.0;
430+
A(l*3+k, 1*3+k) = light[0];
431+
A(l*3+k, 2*3+k) = light[1];
432+
if(!first_degree) {
433+
A(l*3+k, 3*3+k) = light[0]*light[0];
434+
A(l*3+k, 4*3+k) = light[0]*light[1];
435+
A(l*3+k, 5*3+k) = light[1]*light[1];
436+
}
437+
}
440438
}
441-
}
442-
mat.svd.compute(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
439+
}
440+
mat.svd.compute(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
441+
mat.useEigen = true;
443442
} else {
444443
if(colorspace == LRGB) {
445444
//we could generalize for different polynomials
@@ -556,7 +555,7 @@ MaterialBuilder RtiBuilder::pickBase(PixelArray &sample, std::vector<Vector3f> &
556555
case H: builder = pickBaseHSH(directions, type); break;
557556
default: cerr << "Unknown basis" << endl; exit(0);
558557
}
559-
/*
558+
/*
560559
uint32_t dim = sample.components()*3;
561560
for(uint32_t p = 0; p < nplanes; p += 3) {
562561
for(uint32_t k = 0; k < lights.size(); k ++) {
@@ -653,8 +652,8 @@ void RtiBuilder::minmaxMaterial(PixelArray &sample) {
653652
if(callback && (i % 8000) == 0)
654653
if(!(*callback)("Coefficients quantization:", 100*i/sample.npixels()))
655654
throw std::string("Cancelled.");
656-
\
657-
vector<float> principal = toPrincipal(sample[i]);
655+
\
656+
vector<float> principal = toPrincipal(sample[i]);
658657

659658
//find max and min of coefficients
660659
for(uint32_t p = 0; p < nplanes; p++) {
@@ -930,8 +929,8 @@ Vector3f RtiBuilder::getNormalThreeLights(vector<float> &pri) {
930929
Vector3f l2(sin(a)*cos(9*b), sin(a)*sin(9*b), cos(a));
931930

932931
T << l0[0], l0[1], l0[2],
933-
l1[0], l1[1], l1[2],
934-
l2[0], l2[1], l2[2];
932+
l1[0], l1[1], l1[2],
933+
l2[0], l2[1], l2[2];
935934

936935
T = T.inverse().eval();
937936

@@ -1407,7 +1406,7 @@ size_t RtiBuilder::save(const string &output, int quality) {
14071406

14081407
// Set spatial resolution if known. Convert to pixels/m as RtiBuilder stores this in mm/pixel
14091408
if (imageset.pixel_size > 0) {
1410-
int dotsPerMeter = round(1000.0/imageset.pixel_size);
1409+
int dotsPerMeter = round(1000.0/imageset.pixel_size);
14111410
normals.setDotsPerMeterX(dotsPerMeter);
14121411
normals.setDotsPerMeterY(dotsPerMeter);
14131412
means.setDotsPerMeterX(dotsPerMeter);
@@ -1946,18 +1945,24 @@ std::vector<float> RtiBuilder::toPrincipal(Pixel &pixel, MaterialBuilder &materi
19461945
float luma = (mean[0] + mean[1] + mean[2])/255; //actually 3 times luma, but balances in the equation below.
19471946

19481947
//fit luminosity.
1949-
for(size_t p = 3; p < nplanes; p++)
1950-
for(size_t k = 0; k < ndimensions; k++)
1951-
res[p] += ((v[k*3] + v[k*3+1] + v[k*3+2])/luma)* materialbuilder.proj[k + (p-3)*ndimensions];
1948+
if(!materialbuilder.useEigen) {
1949+
for(size_t p = 3; p < nplanes; p++)
1950+
for(size_t k = 0; k < ndimensions; k++)
1951+
res[p] += ((v[k*3] + v[k*3+1] + v[k*3+2])/luma)* materialbuilder.proj[k + (p-3)*ndimensions];
1952+
} else {
1953+
Eigen::Map<Eigen::VectorXf> ev(v, ndimensions);
1954+
Eigen::Map<Eigen::VectorXf> eres(&*res.begin() + 3, nplanes);
19521955

1956+
eres = materialbuilder.svd.solve(ev);
1957+
}
19531958
res[0] = mean[0];
19541959
res[1] = mean[1];
19551960
res[2] = mean[2];
19561961

19571962

19581963

19591964
} else { //RGB, YCC
1960-
if(!materialbuilder.svd.computeU()) { //not rank deficient.
1965+
if(!materialbuilder.useEigen) { //not rank deficient.
19611966
vector<float> col(dim);
19621967

19631968
for(size_t k = 0; k < dim; k++)

relightlab/relightlab.pro

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CONFIG += c++17
66
#target_link_libraries( ${APP_NAME} Qt5::Svg )
77

88
DEFINES += QT_DEPRECATED_WARNINGS
9-
DEFINES += _USE_MATH_DEFINES WITH_OPENCV
9+
DEFINES += _USE_MATH_DEFINES #WITH_OPENCV
1010
DEFINES += NOMINMAX
1111

1212
INCLUDEPATH += ../external/
@@ -17,8 +17,8 @@ win32:INCLUDEPATH += ../external/libjpeg-turbo-2.0.6/include \
1717
win32:LIBS += ../external/libjpeg-turbo-2.0.6/lib/jpeg-static.lib
1818

1919
unix:INCLUDEPATH += ../external/eigen-3.3.9/ /usr/include/opencv4
20-
unix:LIBS += -ljpeg -ltiff -lgomp -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_video
21-
#unix:QMAKE_CXXFLAGS += -fopenmp
20+
unix:LIBS += -ljpeg -ltiff -lgomp
21+
#unix:LIBS += -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_video
2222

2323

2424
mac:INCLUDEPATH += /usr/local/Cellar/jpeg-turbo/3.1.0/include \

src/material.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class MaterialBuilder {
4848
public:
4949
std::vector<float> proj;
5050
std::vector<float> mean;
51+
bool useEigen = false;
5152
Eigen::JacobiSVD<Eigen::MatrixXf> svd;
5253
};
5354

0 commit comments

Comments
 (0)