Lut base class, ScoreImage -> ScoreLut
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
|||||||
all: piphoto
|
all: piphoto
|
||||||
|
|
||||||
objects = piphoto.o util.o
|
objects = piphoto.o lut.o util.o
|
||||||
|
|
||||||
piphoto: $(objects) Makefile
|
piphoto: $(objects) Makefile
|
||||||
clang-3.9 -O3 -g -Weverything -Werror --std=c++1z --stdlib=libc++ -o piphoto $(objects) -lc++ -lunwind -lpng
|
clang-3.9 -O3 -g -Weverything -Werror --std=c++1z --stdlib=libc++ -o piphoto $(objects) -lc++ -lunwind -lpng
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ Array<Coord<2>, kColorCheckerSrgb.size()> FindClosest(const Image<X, Y, C>& imag
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, int32_t C>
|
||||||
int32_t ScoreImage(const Image<X, Y, C>& image) {
|
int32_t ScoreLut(const Image<X, Y, C>& image, const Lut& lut) {
|
||||||
static_assert(C == 3);
|
static_assert(C == 3);
|
||||||
|
|
||||||
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
||||||
@@ -79,7 +79,7 @@ int32_t ScoreImage(const Image<X, Y, C>& image) {
|
|||||||
const auto& row = image.at(y);
|
const auto& row = image.at(y);
|
||||||
|
|
||||||
for (int32_t x = 0; x < X; ++x) {
|
for (int32_t x = 0; x < X; ++x) {
|
||||||
const auto& pixel = row.at(x);
|
const auto pixel = lut.MapColor(row.at(x));
|
||||||
|
|
||||||
for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) {
|
for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) {
|
||||||
auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc));
|
auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc));
|
||||||
@@ -138,7 +138,7 @@ int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut3d<LUT_X, LUT_Y, LUT
|
|||||||
[&image, &snapshot, x, y, z, c](int32_t val) {
|
[&image, &snapshot, x, y, z, c](int32_t val) {
|
||||||
auto test_lut = snapshot;
|
auto test_lut = snapshot;
|
||||||
test_lut.at(x).at(y).at(z).at(c) = val;
|
test_lut.at(x).at(y).at(z).at(c) = val;
|
||||||
return ScoreImage(*test_lut.MapImage(image));
|
return ScoreLut(image, test_lut);
|
||||||
});
|
});
|
||||||
// Magic value of 8 is the number of points making up a square, so the number
|
// Magic value of 8 is the number of points making up a square, so the number
|
||||||
// of points that control any given given LUT mapping.
|
// of points that control any given given LUT mapping.
|
||||||
|
|||||||
51
lut.h
51
lut.h
@@ -3,17 +3,41 @@
|
|||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "coord.h"
|
#include "coord.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
class Lut {
|
||||||
|
public:
|
||||||
|
Lut() = default;
|
||||||
|
Lut(const Lut&) = default;
|
||||||
|
virtual ~Lut();
|
||||||
|
|
||||||
|
virtual Color<3> MapColor(const Color<3>& in) const = 0;
|
||||||
|
|
||||||
|
template <int32_t X, int32_t Y, int32_t C>
|
||||||
|
std::unique_ptr<Image<X, Y, C>> MapImage(const Image<X, Y, C>& in) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int32_t X, int32_t Y, int32_t C>
|
||||||
|
std::unique_ptr<Image<X, Y, C>> Lut::MapImage(const Image<X, Y, C>& in) const {
|
||||||
|
auto out = std::make_unique<Image<X, Y, C>>();
|
||||||
|
|
||||||
|
for (int32_t y = 0; y < Y; ++y) {
|
||||||
|
for (int32_t x = 0; x < X; ++x) {
|
||||||
|
Coord<2> coord = {{{{x, y}}}};
|
||||||
|
out->SetPixel(coord, MapColor(in.GetPixel(coord)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Hardcoded to Color<3>, so color dimensions == LUT dimensions
|
|
||||||
template <int32_t X, int32_t Y, int32_t Z>
|
template <int32_t X, int32_t Y, int32_t Z>
|
||||||
class Lut3d : public Array<Array<Array<Color<3>, X>, Y>, Z> {
|
class Lut3d : public Array<Array<Array<Color<3>, X>, Y>, Z>, public Lut {
|
||||||
public:
|
public:
|
||||||
static Lut3d<X, Y, Z> Identity();
|
static Lut3d<X, Y, Z> Identity();
|
||||||
|
|
||||||
Color<3> MapColor(const Color<3>& in) const;
|
Color<3> MapColor(const Color<3>& in) const override;
|
||||||
|
|
||||||
template <int32_t IMG_X, int32_t IMG_Y, int32_t C>
|
|
||||||
std::unique_ptr<Image<IMG_X, IMG_Y, C>> MapImage(const Image<IMG_X, IMG_Y, C>& in) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return value is (root_indices, remainders)
|
// Return value is (root_indices, remainders)
|
||||||
@@ -82,21 +106,6 @@ Color<3> Lut3d<X, Y, Z>::MapColor(const Color<3>& in) const {
|
|||||||
return inter0.Interpolate(inter1, rem.at(2), BlockSize(Z)).Crop();
|
return inter0.Interpolate(inter1, rem.at(2), BlockSize(Z)).Crop();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t Z>
|
|
||||||
template <int32_t IMG_X, int32_t IMG_Y, int32_t C>
|
|
||||||
std::unique_ptr<Image<IMG_X, IMG_Y, C>> Lut3d<X, Y, Z>::MapImage(const Image<IMG_X, IMG_Y, C>& in) const {
|
|
||||||
auto out = std::make_unique<Image<IMG_X, IMG_Y, C>>();
|
|
||||||
|
|
||||||
for (int32_t y = 0; y < IMG_Y; ++y) {
|
|
||||||
for (int32_t x = 0; x < IMG_X; ++x) {
|
|
||||||
Coord<2> coord = {{{{x, y}}}};
|
|
||||||
out->SetPixel(coord, MapColor(in.GetPixel(coord)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t Z>
|
template <int32_t X, int32_t Y, int32_t Z>
|
||||||
constexpr std::pair<Coord<3>, Coord<3>> Lut3d<X, Y, Z>::FindRoot(const Color<3>& in) {
|
constexpr std::pair<Coord<3>, Coord<3>> Lut3d<X, Y, Z>::FindRoot(const Color<3>& in) {
|
||||||
auto root_x = FindChannelRoot(in.at(0), X);
|
auto root_x = FindChannelRoot(in.at(0), X);
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
int main() {
|
int main() {
|
||||||
auto image = PiRaw2::FromJpeg(ReadFile("test.jpg"));
|
auto image = PiRaw2::FromJpeg(ReadFile("test.jpg"));
|
||||||
WriteFile("start.png", HighlightClosest(*image)->ToPng());
|
WriteFile("start.png", HighlightClosest(*image)->ToPng());
|
||||||
std::cout << "Initial error: " << ScoreImage(*image) << std::endl;
|
|
||||||
|
|
||||||
auto lut = MinimalLut3d::Identity();
|
auto lut = MinimalLut3d::Identity();
|
||||||
|
std::cout << "Initial error: " << ScoreLut(*image, lut) << std::endl;
|
||||||
|
|
||||||
int32_t diff = 1;
|
int32_t diff = 1;
|
||||||
while (diff) {
|
while (diff) {
|
||||||
diff = OptimizeLut<4>(*image, &lut);
|
diff = OptimizeLut<4>(*image, &lut);
|
||||||
std::cout << "diff=" << diff << " error=" << ScoreImage(*lut.MapImage(*image)) << std::endl;
|
std::cout << "diff=" << diff << " error=" << ScoreLut(*image, lut) << std::endl;
|
||||||
WriteFile("inter.png", HighlightClosest(*lut.MapImage(*image))->ToPng());
|
WriteFile("inter.png", HighlightClosest(*lut.MapImage(*image))->ToPng());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user