diff --git a/relight/normalstask.cpp b/relight/normalstask.cpp index 6ba4f796..00ff7a13 100644 --- a/relight/normalstask.cpp +++ b/relight/normalstask.cpp @@ -3,6 +3,7 @@ #include "../src/jpeg_encoder.h" #include "../src/imageset.h" #include "../src/relight_threadpool.h" +#include "../src/flatnormals.h" #include #include @@ -52,7 +53,7 @@ void NormalsTask::run() } imageSet.crop(m_Crop.left(), m_Crop.top(), m_Crop.width(), m_Crop.height()); - std::vector normals(imageSet.width * imageSet.height * 3); + std::vector normals(imageSet.width * imageSet.height * 3); // Thread pool used to handle the processors RelightThreadPool pool; @@ -68,7 +69,7 @@ void NormalsTask::run() // Create the normal task and get the run lambda uint32_t idx = i * 3 * imageSet.width; - uint8_t* data = normals.data() + idx; + double* data = normals.data() + idx; std::function run = [this, &line, &imageSet, data](void)->void { NormalsWorker task(m_Method, line, data, imageSet.lights); @@ -84,8 +85,31 @@ void NormalsTask::run() // Wait for the end of all the threads pool.finish(); + + if(m_FlatMethod != NONE) { + NormalsImage ni; + ni.load(normals, imageSet.width, imageSet.height); + switch(m_FlatMethod) { + case RADIAL: + ni.flattenRadial(); + break; + case FOURIER: + //convert radius to frequencies + double sigma = 100/m_FlatRadius; + ni.flattenFourier(imageSet.width/10, sigma); + break; + } + normals = ni.normals; + } + + // Convert double to uint8_t; + std::vector colors(imageSet.width * imageSet.height * 3); + for(size_t i = 0; i < normals.size(); i++) { + colors[i] = floor(((normals[i] + 1.0f) / 2.0f) * 255); + } + // Save the final result - QImage img(normals.data(), imageSet.width, imageSet.height, imageSet.width*3, QImage::Format_RGB888); + QImage img(colors.data(), imageSet.width, imageSet.height, imageSet.width*3, QImage::Format_RGB888); img.save(m_OutputFolder); progressed("Cleaning up...", 99); @@ -164,10 +188,9 @@ void NormalsWorker::solveL2() mNormals.col(0).normalize(); // Save - m_Normals[normalIdx] = floor(((mNormals(0, 0) + 1.0f) / 2.0f) * 255); - m_Normals[normalIdx+1] = floor(((mNormals(1, 0) + 1.0f) / 2.0f) * 255); - m_Normals[normalIdx+2] = floor(((mNormals(2, 0) + 1.0f) / 2.0f) * 255); - + m_Normals[normalIdx] = mNormals(0, 0); + m_Normals[normalIdx+1] = mNormals(1, 0); + m_Normals[normalIdx+2] = mNormals(2, 0); normalIdx += 3; } } diff --git a/relight/normalstask.h b/relight/normalstask.h index c4235cb1..fbcc9e92 100644 --- a/relight/normalstask.h +++ b/relight/normalstask.h @@ -15,12 +15,16 @@ class NormalsTask : public Task { public: - NormalsTask(QString& inputPath, QString& outputPath, QRect crop, uint32_t method) : - m_InputFolder(inputPath), m_OutputFolder(outputPath), m_Crop(crop), m_Method(method){} + + enum FlatMethod { NONE, RADIAL, FOURIER }; + NormalsTask(QString& inputPath, QString& outputPath, QRect crop, uint32_t method, FlatMethod flatMethod, double flatRadius = 50) : + m_InputFolder(inputPath), m_OutputFolder(outputPath), m_Crop(crop), m_Method(method), m_FlatMethod (flatMethod), m_FlatRadius(flatRadius) {} virtual ~NormalsTask(){}; virtual void run() override; + + public slots: bool progressed(std::string str, int percent) override; private: @@ -28,12 +32,14 @@ public slots: QString m_OutputFolder; QRect m_Crop; uint32_t m_Method; + FlatMethod m_FlatMethod; + double m_FlatRadius; }; class NormalsWorker { public: - NormalsWorker(unsigned int method, PixelArray& toProcess, uint8_t* normals, std::vector lights) : + NormalsWorker(unsigned int method, PixelArray& toProcess, double* normals, std::vector lights) : m_Method(method), m_Row(toProcess), m_Normals(normals), m_Lights(lights){} void run(); @@ -44,7 +50,7 @@ class NormalsWorker private: uint32_t m_Method; PixelArray m_Row; - uint8_t* m_Normals; + double* m_Normals; std::vector m_Lights; QMutex m_Mutex; }; diff --git a/relight/relight.pro b/relight/relight.pro index 157f2390..57b819ad 100644 --- a/relight/relight.pro +++ b/relight/relight.pro @@ -17,7 +17,7 @@ win32:INCLUDEPATH += ../external/libjpeg-turbo-2.0.6/include \ win32:LIBS += ../external/libjpeg-turbo-2.0.6/lib/jpeg-static.lib unix:INCLUDEPATH += /usr/include/eigen3 -unix:LIBS += -ljpeg -liomp5 +unix:LIBS += -ljpeg -liomp5 -lfftw3 #-lfftw3f -lfftw3l unix:QMAKE_CXXFLAGS += -fopenmp @@ -40,6 +40,7 @@ SOURCES += main.cpp \ graphics_view_zoom.cpp \ normalstask.cpp \ rtiexport.cpp \ + ../relight-cli/convert_rti.cpp \ ../relight-cli/rtibuilder.cpp \ ../src/imageset.cpp \ ../src/jpeg_decoder.cpp \ @@ -48,6 +49,8 @@ SOURCES += main.cpp \ ../src/legacy_rti.cpp \ ../src/deepzoom.cpp \ ../src/exif.cpp \ + ../src/flatnormals.cpp \ + ../src/lp.cpp \ dome.cpp \ helpdialog.cpp \ project.cpp \ @@ -64,9 +67,7 @@ SOURCES += main.cpp \ task.cpp \ rtitask.cpp \ settingsdialog.cpp \ - ../relight-cli/convert_rti.cpp \ domecalibration.cpp \ - ../src/lp.cpp \ qmarkerlist.cpp \ qmarker.cpp \ qmeasuremarker.cpp \ @@ -84,7 +85,6 @@ SOURCES += main.cpp \ HEADERS += \ - ../src/deepzoom.h \ dstretch.h \ dstretchdialog.h \ dstretchtask.h \ @@ -97,17 +97,24 @@ HEADERS += \ helpdialog.h \ ../src/imageset.h \ ../src/jpeg_decoder.h \ - ../src/jpeg_encoder.h \ ../src/material.h \ ../src/eigenpca.h \ ../relight-cli/rtibuilder.h \ ../src/relight_threadpool.h \ + ../src/relight_vector.h \ + ../src/lp.h \ + ../src/deepzoom.h \ + ../src/flatnormals.h \ + ../src/exif.h \ + ../src/legacy_rti.h \ + ../src/relight_vector.h \ + ../src/lp.h \ + ../src/flatnormals.h \ project.h \ measure.h \ focaldialog.h \ lens.h \ image.h \ - ../src/exif.h \ httpserver.h \ scripts.h \ processqueue.h \ @@ -117,12 +124,9 @@ HEADERS += \ task.h \ rtitask.h \ settingsdialog.h \ - ../src/legacy_rti.h \ httplib.h \ domecalibration.h \ dome.h \ - ../src/relight_vector.h \ - ../src/lp.h \ qmarker.h \ qmarkerlist.h \ qmeasuremarker.h \ @@ -136,8 +140,7 @@ HEADERS += \ aligndialog.h \ zoom.h \ zoomdialog.h \ - zoomtask.h \ - ../src/deepzoom.h + zoomtask.h FORMS += \ dstretchdialog.ui \ diff --git a/relight/rtiexport.cpp b/relight/rtiexport.cpp index 89beeb75..173dc6f4 100644 --- a/relight/rtiexport.cpp +++ b/relight/rtiexport.cpp @@ -251,8 +251,17 @@ void RtiExport::createNormals() { if(ui->rpca_solver->isChecked()) method = 5; - ProcessQueue &queue = ProcessQueue::instance(); - NormalsTask *task = new NormalsTask(path, output, crop, method); + NormalsTask::FlatMethod flat_method; + if(ui->flat_none->isChecked()) + flat_method = NormalsTask::FlatMethod::NONE; + if(ui->flat_radial->isChecked()) + flat_method = NormalsTask::FlatMethod::RADIAL; + if(ui->flat_fourier->isChecked()) + flat_method = NormalsTask::FlatMethod::FOURIER; + + double flat_radius = ui->flat_fourier_radius->value(); + ProcessQueue &queue = ProcessQueue::instance(); + NormalsTask *task = new NormalsTask(path, output, crop, method, flat_method, flat_radius); QList slights; for(auto light: lights) diff --git a/relight/rtiexport.ui b/relight/rtiexport.ui index 77c31428..d2d07f45 100644 --- a/relight/rtiexport.ui +++ b/relight/rtiexport.ui @@ -27,7 +27,7 @@ - 0 + 1 @@ -286,8 +286,8 @@ Normals - - + + Solver @@ -326,7 +326,54 @@ - + + + + Flatten normals + + + + + + None + + + true + + + + + + + Radial + + + + + + + Fourier + + + + + + + Radius (0 - 100%): + + + + + + + 20.000000000000000 + + + + + + + Crop... @@ -337,7 +384,7 @@ - + Qt::Vertical @@ -350,7 +397,7 @@ - + Build diff --git a/relight/sphere.cpp b/relight/sphere.cpp index 98aace8e..be2ec008 100644 --- a/relight/sphere.cpp +++ b/relight/sphere.cpp @@ -57,12 +57,11 @@ void Sphere::resetHighlight(size_t n) { void Sphere::ellipseFit() { size_t n = border.size(); - Eigen::MatrixXd D1(n, 3); Eigen::MatrixXd D2(n, 3); for(size_t k = 0; k < border.size(); k++) { - double x = X(k)= border[k].x(); - double y = Y(k)= border[k].y(); + double x = border[k].x(); + double y = border[k].y(); D1(k, 0) = x*x; D1(k, 1) = x*y; D1(k, 2) = y*y; @@ -96,9 +95,10 @@ void Sphere::ellipseFit() { Eigen::VectorXd cond = 4 * row0.array() * row2.array() - row1.array().pow(2); - Eigen::VectorXd ellipse = eigenvector.col(0) + Eigen::VectorXd ellipse = eigenvector.col(0); + Eigen::VectorXd min_pos_eig; - for(int i= 0; i<3 ; i++){ + for(int i = 0; i<3 ; i++) { if(cond(i) > 0){ min_pos_eig = eigenvector.col(i); break;