Skip to content

Commit 19ef1cd

Browse files
committed
bgfixing normals export.
1 parent 8026256 commit 19ef1cd

9 files changed

+110
-92
lines changed

relight-cli/rtibuilder.cpp

+19-21
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,8 @@ bool RtiBuilder::setupFromFolder(const string &folder) {
9797
imageset.images.removeAt(skip_image);
9898
dome.directions.erase(dome.directions.begin() + skip_image);
9999
}
100-
imageset.lights1 = dome.directions;
101-
imageset.light3d = false;
102-
103100
imageset.initImages(folder.c_str());
104-
101+
imageset.setLights(dome.directions, Dome::DIRECTIONAL);
105102

106103
} catch(QString e) {
107104
error = e.toStdString();
@@ -474,13 +471,13 @@ MaterialBuilder RtiBuilder::pickBaseHSH(std::vector<Vector3f> &lights, Rti::Type
474471
void RtiBuilder::pickBases(PixelArray &sample) {
475472
//rbf can't 3d, bilinear just resample (and then single base)
476473
if(!imageset.light3d) {
477-
materialbuilder = pickBase(sample, imageset.lights1);
474+
materialbuilder = pickBase(sample, imageset.lights());
478475

479476
} else {
480477

481478
if(type == RBF || type == BILINEAR) {
482479

483-
materialbuilder = pickBase(sample, imageset.lights1); //lights are unused for rbf
480+
materialbuilder = pickBase(sample, imageset.lights()); //lights are unused for rbf
484481

485482
} else {
486483
materialbuilders.resize(resample_width * resample_height);
@@ -782,14 +779,14 @@ bool RtiBuilder::saveJSON(QDir &dir, int quality) {
782779
}
783780
stream << "\",\n";
784781

785-
if(imageset.lights1.size()) {
782+
if(imageset.lights().size()) {
786783
if(type == RBF)
787784
stream << "\"sigma\": " << sigma << ",\n";
788785
stream << "\"lights\": [";
789-
for(uint32_t i = 0; i < imageset.lights1.size(); i++) {
790-
Vector3f &l = imageset.lights1[i];
786+
for(uint32_t i = 0; i < imageset.lights().size(); i++) {
787+
Vector3f &l = imageset.lights()[i];
791788
stream << QString::number(l[0], 'f', 3) << ", " << QString::number(l[1], 'f', 3) << ", " << QString::number(l[2], 'f', 3);
792-
if(i != imageset.lights1.size()-1)
789+
if(i != imageset.lights().size()-1)
793790
stream << ", ";
794791
}
795792
stream << "],\n";
@@ -1296,9 +1293,9 @@ size_t RtiBuilder::save(const string &output, int quality) {
12961293
int side = 32;
12971294
QImage img(side*(nplanes+1), side, QImage::Format_RGB32);
12981295
img.fill(qRgb(0, 0, 0));
1299-
for(uint32_t i = 0; i < imageset.lights1.size(); i++) {
1296+
for(uint32_t i = 0; i < imageset.lights().size(); i++) {
13001297
float dx, dy;
1301-
toOcta(imageset.lights1[i], dx, dy, side);
1298+
toOcta(imageset.lights()[i], dx, dy, side);
13021299
int x = dx;
13031300
int y = dy;
13041301
int r = (int)materialbuilder.mean[i*3+0];
@@ -1310,9 +1307,9 @@ size_t RtiBuilder::save(const string &output, int quality) {
13101307
Material::Plane &plane = material.planes[p];
13111308
float *eigen = materialbuilder.proj.data() + p*dim;
13121309
uint32_t X = (p+1)*side;
1313-
for(size_t i = 0; i < imageset.lights1.size(); i++) {
1310+
for(size_t i = 0; i < imageset.lights().size(); i++) {
13141311
float dx, dy;
1315-
toOcta(imageset.lights1[i], dx, dy, side);
1312+
toOcta(imageset.lights()[i], dx, dy, side);
13161313
uint32_t x = dx;
13171314
int y = dy;
13181315
int r = (int)(127 + plane.range*eigen[i*3+0]);
@@ -1474,10 +1471,11 @@ void RtiBuilder::processLine(PixelArray &sample, PixelArray &resample, std::vect
14741471
for(uint32_t y = 0; y < sample.nlights; y++)
14751472
A(y, 0) = sample[x][y].mean();
14761473

1477-
for(uint32_t y = 0; y < imageset.lights1.size(); y++) {
1478-
b(y, 0) = imageset.lights1[y][0];
1479-
b(y, 1) = imageset.lights1[y][1];
1480-
b(y, 2) = imageset.lights1[y][2];
1474+
for(uint32_t y = 0; y < imageset.lights().size(); y++) {
1475+
Eigen::Vector3f &l = imageset.lights()[y];
1476+
b(y, 0) = l[0];
1477+
b(y, 1) = l[1];
1478+
b(y, 2) = l[2];
14811479
}
14821480

14831481
Eigen::MatrixXf r = (A.transpose() * A).ldlt().solve(A.transpose() * b);
@@ -1685,7 +1683,7 @@ void RtiBuilder::resamplePixel(Pixel &sample, Pixel &pixel) { //pos in pixels.
16851683
//notice how sample are already intensity corrected.
16861684
vector<Vector3f> RtiBuilder::relativeNormalizedLights(int x, int y) {
16871685

1688-
vector<Vector3f> relights = imageset.lights1;;
1686+
vector<Vector3f> relights = imageset.lights();
16891687
for(Vector3f &light: relights) {
16901688
light = imageset.relativeLight(light, x, y);
16911689
light.normalize();
@@ -1695,7 +1693,7 @@ vector<Vector3f> RtiBuilder::relativeNormalizedLights(int x, int y) {
16951693

16961694
void RtiBuilder::buildResampleMaps() {
16971695
if(!imageset.light3d) {
1698-
buildResampleMap(imageset.lights1, resamplemap);
1696+
buildResampleMap(imageset.lights(), resamplemap);
16991697
return;
17001698
}
17011699
resamplemaps.resize(resample_height*resample_width);
@@ -1900,7 +1898,7 @@ std::vector<float> RtiBuilder::toPrincipal(Pixel &pixel, MaterialBuilder &materi
19001898
float weight = 0;
19011899
for(uint32_t i = 0; i < ndimensions; i++) {
19021900
Color3f &c = pixel[i];
1903-
float w = 0.25 - pow(asin(imageset.lights1[i][2])/(M_PI/2) - 0.5, 2);
1901+
float w = 0.25 - pow(asin(imageset.lights()[i][2])/(M_PI/2) - 0.5, 2);
19041902
mean += c*w;
19051903
weight += w;
19061904
}

relightlab/main.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ int main(int argc, char *argv[]) {
1818

1919
RelightApp app(argc, argv);
2020

21+
QApplication::setAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
2122
setlocale(LC_ALL, "en_US.UTF8"); //needs to be called AFTER QApplication creation.
2223

2324
QCoreApplication::setOrganizationName("VCG");

relightlab/normalsframe.cpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,24 @@ void NormalsFrame::init() {
7474
}
7575

7676
void NormalsFrame::save() {
77-
if(parameters.compute && qRelightApp->project().dome.directions.size() == 0) {
78-
QMessageBox::warning(this, "Missing light directions.", "You need light directions for this dataset to build a normalmap.\n"
77+
if(parameters.compute) {
78+
//make sure we have some light directions defined
79+
if(qRelightApp->project().dome.directions.size() == 0) {
80+
QMessageBox::warning(this, "Missing light directions.", "You need light directions for this dataset to build a normalmap.\n"
7981
"You can either load a dome or .lp file or mark a reflective sphere in the 'Lights' tab.");
80-
return;
81-
}
82+
return;
83+
}
84+
} else {
85+
if(parameters.flatMethod == FlatMethod::FLAT_NONE && parameters.surface_integration == SurfaceIntegration::SURFACE_NONE) {
86+
QMessageBox::warning(this, "Nothing to do.", "Using an existing normalmap ma no flattening or integration method specified");
87+
return;
88+
}
8289

90+
if(parameters.input_path == parameters.path) {
91+
QMessageBox::warning(this, "Input and output normalmap have the same name", "The input normal map would be overwritten. Change the output filename");
92+
return;
93+
}
94+
}
8395
NormalsTask *task = new NormalsTask();
8496
task->parameters = parameters;
8597
task->output = parameters.path;

relightlab/normalsplan.cpp

+34-11
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,24 @@ NormalsSourceRow::NormalsSourceRow(NormalsParameters &_parameters, QFrame *paren
2323
label->help->setId("normals/normalmap");
2424

2525
compute = new QLabelButton("Compute", "Compute normals from images");
26-
27-
file = new QLabelButton("Normalmap", "Loat a normalmap image.");
2826
buttons->addWidget(compute, 0, Qt::AlignCenter);
2927

30-
QVBoxLayout *button_layout =new QVBoxLayout;
31-
button_layout->addWidget(file);
32-
33-
QHBoxLayout *loader_layout = new QHBoxLayout;
34-
loader_layout->addWidget(path = new QLineEdit);
35-
loader_layout->addWidget(open = new QPushButton("..."));
3628

37-
button_layout->addLayout(loader_layout);
29+
{
30+
QVBoxLayout *button_layout =new QVBoxLayout;
31+
file = new QLabelButton("Normalmap", "Load a normalmap image.");
3832

33+
button_layout->addWidget(file);
34+
{
35+
QHBoxLayout *loader_layout = new QHBoxLayout;
36+
loader_layout->addWidget(input_path = new QLineEdit);
37+
loader_layout->addWidget(open = new QPushButton("..."));
38+
button_layout->addLayout(loader_layout);
39+
connect(open, &QPushButton::clicked, this, &NormalsSourceRow::selectOutput);
3940

40-
buttons->addLayout(button_layout, 0); //, Qt::AlignCenter);
41+
}
42+
buttons->addLayout(button_layout, 0); //, Qt::AlignCenter);
43+
}
4144

4245
connect(compute, &QAbstractButton::clicked, this, [this](){ setComputeSource(true); });
4346
connect(file, &QAbstractButton::clicked, this, [this](){ setComputeSource(false); });
@@ -59,6 +62,25 @@ void NormalsSourceRow::setComputeSource(bool build) {
5962
}
6063

6164

65+
void NormalsSourceRow::selectOutput() {
66+
//get folder if not legacy.
67+
QString output_parent = qRelightApp->lastOutputDir();
68+
69+
QString output = QFileDialog::getOpenFileName(this, "Select an output folder", output_parent);
70+
if(output.isNull()) return;
71+
72+
QDir output_parent_dir(output);
73+
output_parent_dir.cdUp();
74+
setSourcePath(output);
75+
}
76+
77+
void NormalsSourceRow::setSourcePath(QString path) {
78+
parameters.input_path = path;
79+
input_path->setText(path);
80+
}
81+
82+
83+
6284

6385
NormalsFlattenRow::NormalsFlattenRow(NormalsParameters &_parameters, QFrame *parent):
6486
NormalsPlanRow(_parameters, parent) {
@@ -78,7 +100,8 @@ NormalsFlattenRow::NormalsFlattenRow(NormalsParameters &_parameters, QFrame *par
78100
QHBoxLayout *loader_layout = new QHBoxLayout;
79101
loader_layout->addWidget(new QLabel("Fourier low pass frequency."));
80102
loader_layout->addWidget(max_frequency = new QDoubleSpinBox);
81-
max_frequency->setRange(0.01, 1);
103+
max_frequency->setRange(0.0001, 1);
104+
max_frequency->setDecimals(4);
82105

83106
button_layout->addLayout(loader_layout);
84107

relightlab/normalsplan.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,19 @@ class NormalsPlanRow: public PlanRow {
2020

2121

2222
class NormalsSourceRow: public NormalsPlanRow {
23+
Q_OBJECT
2324
public:
2425
NormalsSourceRow(NormalsParameters &_parameters, QFrame *parent = nullptr);
2526

2627
void setComputeSource(bool compute);
27-
void setSourcePaht(QString path);
28+
void setSourcePath(QString path);
29+
public slots:
30+
void selectOutput();
2831

32+
protected:
2933
QLabelButton *compute = nullptr;
3034
QLabelButton *file = nullptr;
31-
QLineEdit *path = nullptr;
35+
QLineEdit *input_path = nullptr;
3236
QPushButton *open = nullptr;
3337
};
3438

relightlab/normalstask.cpp

+12-15
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void NormalsTask::initFromProject(Project &project) {
4040
imageset.images = project.getImages();
4141
imageset.initImages(project.dir.absolutePath().toStdString().c_str());
4242
imageset.initFromDome(project.dome);
43-
assert(imageset.lights1.size() == imageset.images.size());
43+
assert(imageset.lights().size() == imageset.images.size());
4444
QRect &crop = project.crop;
4545
if(!crop.isNull()) {
4646
imageset.crop(crop.left(), crop.top(), crop.width(), crop.height());
@@ -124,16 +124,16 @@ void NormalsTask::run() {
124124
normalsd[i] = (double)normals[i];
125125

126126
NormalsImage ni;
127-
ni.load(normalsd, imageset.width, imageset.height);
127+
ni.load(normalsd, width, height);
128128
switch(parameters.flatMethod) {
129129
case FLAT_NONE: break;
130130
case FLAT_RADIAL:
131131
ni.flattenRadial();
132132
break;
133133
case FLAT_FOURIER:
134134
//convert radius to frequencies
135-
double sigma = 100/parameters.m_FlatRadius;
136-
ni.flattenFourier(imageset.width/10, sigma);
135+
double sigma = 100*parameters.m_FlatRadius;
136+
ni.flattenFourier(width/10, sigma);
137137
break;
138138
}
139139
normalsd = ni.normals;
@@ -145,11 +145,11 @@ void NormalsTask::run() {
145145
if(parameters.compute || parameters.flatMethod != FLAT_NONE) {
146146
// Save the normals
147147

148-
vector<uint8_t> normalmap(imageset.width * imageset.height * 3);
148+
vector<uint8_t> normalmap(width * height * 3);
149149
for(size_t i = 0; i < normals.size(); i++)
150150
normalmap[i] = floor(((normals[i] + 1.0f) / 2.0f) * 255);
151151

152-
QImage img(normalmap.data(), imageset.width, imageset.height, imageset.width*3, QImage::Format_RGB888);
152+
QImage img(normalmap.data(), width, height, width*3, QImage::Format_RGB888);
153153

154154

155155
// Set spatial resolution if known. Need to convert as pixelSize stored in mm/pixel whereas QImage requires pixels/m
@@ -158,7 +158,7 @@ void NormalsTask::run() {
158158
img.setDotsPerMeterX(dotsPerMeter);
159159
img.setDotsPerMeterY(dotsPerMeter);
160160
}
161-
img.save(output);
161+
img.save(parameters.path);
162162

163163
}
164164

@@ -177,7 +177,7 @@ void NormalsTask::run() {
177177
return;
178178

179179
vector<float> z;
180-
bni_integrate(callback, imageset.width, imageset.height, normals, z, parameters.bni_k);
180+
bni_integrate(callback, width, height, normals, z, parameters.bni_k);
181181
if(z.size() == 0) {
182182
error = "Failed to integrate normals";
183183
status = FAILED;
@@ -187,7 +187,7 @@ void NormalsTask::run() {
187187

188188
progressed("Saving surface...", 99);
189189
QString filename = output.left(output.size() -4) + ".ply";
190-
savePly(filename, imageset.width, imageset.height, z);
190+
savePly(filename, width, height, z);
191191
}
192192
progressed("Done", 100);
193193
}
@@ -220,8 +220,8 @@ bool saveObj(const char *filename, pmp::SurfaceMesh &mesh) {
220220

221221
void NormalsTask::assm(QString filename, vector<float> &_normals, float approx_error) {
222222
Grid<Eigen::Vector3f> normals(imageset.width, imageset.height, Eigen::Vector3f(0.0f, 0.0f, 0.0f));
223-
for(size_t y = 0; y < imageset.height; y++)
224-
for(size_t x = 0; x < imageset.width; x++) {
223+
for(int y = 0; y < imageset.height; y++)
224+
for(int x = 0; x < imageset.width; x++) {
225225
int i = 3*(x + y*imageset.width);
226226
normals.at(y, x) = Eigen::Vector3f(-_normals[i+0], -_normals[i+1], -_normals[i+2]);
227227
}
@@ -245,15 +245,12 @@ void NormalsTask::assm(QString filename, vector<float> &_normals, float approx_e
245245
void NormalsWorker::run() {
246246
switch (solver)
247247
{
248-
// L2 solver
249248
case NORMALS_L2:
250249
solveL2();
251250
break;
252-
// SBL solver
253251
case NORMALS_SBL:
254252
solveSBL();
255253
break;
256-
// RPCA solver
257254
case NORMALS_RPCA:
258255
solveRPCA();
259256
break;
@@ -264,7 +261,7 @@ void NormalsWorker::run() {
264261

265262
void NormalsWorker::solveL2()
266263
{
267-
vector<Vector3f> &m_Lights = m_Imageset.lights1;
264+
vector<Vector3f> &m_Lights = m_Imageset.lights();
268265

269266
// Pixel data
270267
Eigen::MatrixXd mLights(m_Lights.size(), 3);

0 commit comments

Comments
 (0)