Skip to content

Commit

Permalink
Major Refactor: Changing the structure of the project and adopt moder…
Browse files Browse the repository at this point in the history
…n C++
  • Loading branch information
KaoCC committed Dec 26, 2021
1 parent a8ca877 commit 1b1a415
Show file tree
Hide file tree
Showing 31 changed files with 670 additions and 786 deletions.
5 changes: 5 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
BasedOnStyle: Google
ColumnLimit: '120'

...
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@

Build/*
Generated/*

.vscode/*
26 changes: 6 additions & 20 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


cmake_minimum_required(VERSION 3.6)
cmake_minimum_required(VERSION 3.8)

set(CMAKE_CXX_STANDARD 17)

Expand Down Expand Up @@ -28,8 +28,6 @@ else()
endif()




project(HDR LANGUAGES CXX)

set(CMAKE_VERBOSE_MAKEFILE TRUE)
Expand All @@ -51,14 +49,6 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "C
endif()


# set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
# set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)


# find_package(OpenCV REQUIRED)
# add_subdirectory(HDRI)


#debug messages
message("CMAKE_BUILD_TYPE= ${CMAKE_BUILD_TYPE}")
message("CMAKE_SOURCE_DIR= ${CMAKE_SOURCE_DIR}")
Expand All @@ -72,16 +62,13 @@ message("CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
message("CMAKE_GENERATOR= ${CMAKE_GENERATOR}")



set(BASE_SRC

HDRI/src/Common.cpp
HDRI/src/HDRImage.cpp
HDRI/src/LinearLeastSquares.cpp
HDRI/src/DebevecWeight.cpp
HDRI/src/rawImage.cpp
HDRI/src/ReinhardAlgo.cpp
HDRI/src/main.cpp
HDRI/hdr_image.cpp
HDRI/debevec_weight.cpp
HDRI/raw_image.cpp
HDRI/tone_map_algo.cpp
HDRI/main.cpp
)


Expand All @@ -91,7 +78,6 @@ add_executable(
)

include_directories(${HDRI_DIR}/include)
# include_directories( ${OpenCV_INCLUDE_DIRS} )

target_link_libraries( hdri ${CONAN_LIBS} )
target_compile_features(hdri PUBLIC cxx_std_17)
Expand Down
10 changes: 10 additions & 0 deletions HDRI/common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

#pragma once

#include <cstdint>

struct pixel {
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
};
33 changes: 33 additions & 0 deletions HDRI/debevec_weight.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "debevec_weight.hpp"

namespace {
constexpr int z_min = 0;
constexpr int z_max = 255;
constexpr int range = z_max - z_min + 1;
} // namespace

namespace HDRI {

debevec_weight::debevec_weight() {
table.resize(range);
for (auto i = 0; i < range; ++i) {
if (i <= (0.5 * (z_max + z_min))) {
table[i] = static_cast<std::uint8_t>(i - z_min);
} else {
table[i] = static_cast<std::uint8_t>(z_max - i);
}
}
}

auto debevec_weight::get_size() const noexcept -> size_t { return range; }

auto debevec_weight::get_weight(int index) const noexcept -> double {
// cap ?

if (index < z_min || index > z_max) {
return 0;
}
return table[index];
}

} // namespace HDRI
17 changes: 17 additions & 0 deletions HDRI/debevec_weight.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <vector>

namespace HDRI {

class debevec_weight final {
public:
debevec_weight();
[[nodiscard]] double get_weight(const int index) const noexcept;
[[nodiscard]] std::size_t get_size() const noexcept;

private:
std::vector<std::uint8_t> table;
};

} // namespace HDRI
179 changes: 179 additions & 0 deletions HDRI/hdr_image.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@

#include "hdr_image.hpp"

#include <future>
#include <opencv2/imgproc.hpp>

#include "common.hpp"
#include "debevec_weight.hpp"
#include "linear_least_square_solver.hpp"
#include "raw_image.hpp"

namespace {

template <typename weight_function>
cv::Mat construct_radiance(const std::vector<HDRI::raw_image> &image_files, const std::array<cv::Mat, 3UL> &curves,
weight_function &&weighting, const std::vector<double> &expo) noexcept {
// Size
const auto width = image_files[0UL].get_width();
const auto height = image_files[0UL].get_height();

// Radiance
cv::Mat radiance(height, width, CV_32FC3);

for (auto idx = 0UL; idx < std::size(curves); ++idx) { // r, g, b
for (auto y = 0UL; y < height; ++y) {
for (auto x = 0UL; x < width; ++x) {
double weighted_sum = 0.0;
double result = 0.0;

// loop over all images
for (auto k = 0UL; k < std::size(image_files); ++k) {
const auto color = static_cast<int>(image_files[k].get_image_data().at<cv::Vec3b>(y, x)[idx]);
const double w = std::invoke(std::forward<weight_function>(weighting), color);

result += static_cast<double>(w * (curves[idx].at<double>(color, 0) - std::log(expo[k])));
weighted_sum += w;
}

if (weighted_sum < std::numeric_limits<double>::epsilon() &&
weighted_sum > -std::numeric_limits<double>::epsilon()) { // near 0.0
radiance.at<cv::Vec3f>(y, x)[idx] = 0;
} else {
radiance.at<cv::Vec3f>(y, x)[idx] = std::exp(result / weighted_sum);
}
}
}
}

return radiance;
}

std::vector<cv::Mat> shrink_images(const std::vector<HDRI::raw_image> &input) noexcept {
std::vector<cv::Mat> out;
out.reserve(std::size(input));

constexpr size_t ratio = 100UL;

for (const auto &img : input) {
const auto &image_data = img.get_image_data();

size_t resized_col = image_data.cols / ratio;
size_t resized_row = image_data.rows / ratio;

if (resized_col < 15UL) {
resized_col = 15UL;
}

if (resized_row < 15UL) {
resized_row = 15UL;
}

cv::Mat shrink_mat;
cv::resize(image_data, shrink_mat, cv::Size(image_data.cols, image_data.rows));
cv::resize(shrink_mat, shrink_mat, cv::Size(resized_col, resized_row));

out.push_back(shrink_mat);
}

return out;
}

std::vector<std::vector<pixel>> generate_raw_pixel(const std::vector<cv::Mat> &shrink_mat) noexcept {
const auto width = shrink_mat[0UL].size().width;
const auto height = shrink_mat[0UL].size().height;

std::vector<std::vector<pixel>> pixels(shrink_mat.size());

for (auto idx = 0UL; idx < shrink_mat.size(); ++idx) {
pixels[idx].resize(width * height);

for (auto y = 0UL; y < height; ++y) {
for (auto x = 0UL; x < width; ++x) {
pixels[idx][y * width + x].b = shrink_mat[idx].at<cv::Vec3b>(y, x)[0UL];
pixels[idx][y * width + x].g = shrink_mat[idx].at<cv::Vec3b>(y, x)[1UL];
pixels[idx][y * width + x].r = shrink_mat[idx].at<cv::Vec3b>(y, x)[2UL];
}
}
}

return pixels;
}

std::array<std::vector<std::vector<int>>, 3UL> convert_to_z(const std::vector<std::vector<pixel>> &pixel,
const size_t image_size, const size_t num_images) noexcept {
std::array<std::vector<std::vector<int>>, 3UL> z_values; // r, g, b

for (auto &z_colors : z_values) {
z_colors.resize(image_size);
}

for (size_t i = 0; i < image_size; ++i) { // image pixel

z_values[0UL][i].resize(num_images);
z_values[1UL][i].resize(num_images);
z_values[2UL][i].resize(num_images);

for (size_t j = 0; j < num_images; ++j) { // num of iamge
z_values[0UL][i][j] = pixel[j][i].b;
z_values[1UL][i][j] = pixel[j][i].g;
z_values[2UL][i][j] = pixel[j][i].r;
}
}

return z_values;
}

} // namespace

namespace HDRI {

hdr_image::hdr_image(const std::vector<raw_image> &raw_images) {
// set exposure
std::vector<double> exposure;
exposure.reserve(std::size(raw_images));

for (const auto &raw_image : raw_images) {
exposure.push_back(raw_image.get_exposure());
}

compute_curves(raw_images, exposure);
compute_radiance(raw_images, exposure);
}

const std::array<cv::Mat, 3UL> &hdr_image::get_curves() const noexcept { return curves; }

void hdr_image::compute_curves(const std::vector<HDRI::raw_image> &raw_images,
const std::vector<double> &exposure) noexcept {
const auto shrink_mat = shrink_images(raw_images);
std::vector<std::vector<pixel>> raw_pixel = generate_raw_pixel(shrink_mat);

// convert
const auto z_values = convert_to_z(raw_pixel, shrink_mat[0UL].total(), shrink_mat.size());

debevec_weight dwf;
constexpr auto lambda = 10;

const auto weight_function = [&dwf](const auto color_index) { return dwf.get_weight(color_index); };

std::array<std::future<cv::Mat>, 3UL> futures;
for (auto c = 0U; c < std::size(z_values); ++c) {
futures[c] = std::async(std::launch::async, linear_least_square_solver<decltype(weight_function)>, weight_function,
z_values[c], exposure, dwf.get_size(), lambda);
}

for (auto c = 0U; c < std::size(futures); ++c) {
curves[c] = futures[c].get();
}
}

void hdr_image::compute_radiance(const std::vector<HDRI::raw_image> &raw_images,
const std::vector<double> &exposure) noexcept {
debevec_weight dwf;
radiance = construct_radiance(
raw_images, curves, [&dwf](auto color_index) { return dwf.get_weight(color_index); }, exposure);
}

const cv::Mat &hdr_image::get_radiance() const noexcept { return radiance; }

} // namespace HDRI
33 changes: 33 additions & 0 deletions HDRI/hdr_image.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

#pragma once

#include <array>
#include <opencv2/core/mat.hpp>

namespace HDRI {
class raw_image;

class hdr_image final {
public:
explicit hdr_image(const std::vector<raw_image> &raw_images);

[[nodiscard]] const cv::Mat &get_radiance() const noexcept;
[[nodiscard]] const std::array<cv::Mat, 3UL> &get_curves() const noexcept;

template <typename mapping_function>
[[nodiscard]] cv::Mat compute_tone_mapping(mapping_function &&algo) const noexcept;

private:
void compute_curves(const std::vector<raw_image> &raw_images, const std::vector<double> &expo) noexcept;
void compute_radiance(const std::vector<raw_image> &raw_images, const std::vector<double> &expo) noexcept;

std::array<cv::Mat, 3UL> curves;
cv::Mat radiance;
};

template <typename mapping_function>
cv::Mat hdr_image::compute_tone_mapping(mapping_function &&algo) const noexcept {
return std::invoke(std::forward<mapping_function>(algo), radiance);
}

} // namespace HDRI
22 changes: 0 additions & 22 deletions HDRI/include/Common.hpp

This file was deleted.

Loading

0 comments on commit 1b1a415

Please sign in to comment.