From c5fb1155aec4eaf193fe94ebf169f7ee25bc7c33 Mon Sep 17 00:00:00 2001 From: Michael Kuc Date: Tue, 4 Sep 2018 21:05:31 +0100 Subject: [PATCH] Implemented histogram matching --- Build.sh | 3 ++ Solver.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100755 Build.sh create mode 100644 Solver.cpp diff --git a/Build.sh b/Build.sh new file mode 100755 index 0000000..548ab61 --- /dev/null +++ b/Build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +g++ --std=c++17 -lopencv_core -lopencv_imgproc -lopencv_imgcodecs Solver.cpp -O3 -o Solver diff --git a/Solver.cpp b/Solver.cpp new file mode 100644 index 0000000..ab63c06 --- /dev/null +++ b/Solver.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +array getHistograms(const Mat &img); +array getCumulativeHistograms(const Mat &img); +array, 3> getLUT(const Mat &img, const array &refCumHist); +Mat doLUT(const string &filename, const array &refCumHist); + +int main() +{ + const constexpr size_t digitCount = 5; + const constexpr size_t frameCount = 20505; + auto refHistos = getCumulativeHistograms(imread("Frame00001.png", IMREAD_COLOR)); + + for (size_t i = 2; i < frameCount; i++) + { + clog << "Processing frame: " << i << endl; + string filename{ "Frame" }; + string numeric{ to_string(i) }; + + filename += string(digitCount - numeric.size(), '0') + numeric + ".png"; + + const auto lutted = doLUT(filename, refHistos); + imwrite("processed/" + filename, lutted); + } + + return 0; +} + +array getHistograms(const Mat &img) +{ + array compPlanes; + split(img, compPlanes); + + const int histSize = 256; + + const float range[]{ 0.f, 256.f }; + const float* histRange{ range }; + bool uniform = true, accumulate = false; + + array histos; + + for (size_t i = 0u; i < 3; i++) + calcHist(&compPlanes[i], 1, nullptr, Mat{}, histos[i], 1, &histSize, &histRange, uniform, accumulate); + + for (size_t histI = 0u; histI < histos.size(); histI++) + { + double histTotal = 0.0; + + for (size_t i = 0u; i < histos[histI].rows; i++) + histTotal += histos[histI].at(i); + + for (size_t i = 0u; i < histos[histI].rows; i++) + histos[histI].at(i) /= histTotal; + } + + return histos; +} + +array getCumulativeHistograms(const Mat &img) +{ + auto histos = getHistograms(img); + + for (size_t histI = 0; histI < histos.size(); histI++) + { + double cumulativeTotal = 0.0; + + for (size_t i = 0; i < histos[histI].rows; i++) + { + cumulativeTotal += histos[histI].at(i); + histos[histI].at(i) = cumulativeTotal; + } + } + + return histos; +} + +array, 3> getLUT(const Mat &img, const array &refCumHist) +{ + const auto cumulativeHistos = getCumulativeHistograms(img); + array, 3> luts{}; + + auto comp = [](float a, float b){ return (b - a) > 1.0e-6f; }; + + for (size_t lut = 0; lut < luts.size(); lut++) + { + uint16_t targetBin = 1; + + for (uint16_t bin = 0; bin < luts[lut].size(); bin++) + { + while (comp(refCumHist[lut].at(targetBin), cumulativeHistos[lut].at(bin)) && targetBin < luts[lut].size()) + targetBin++; + + luts[lut][bin] = targetBin - 1; + } + } + + return luts; +} + +Mat doLUT(const string &filename, const array &refCumHist) +{ + Mat img{ imread(filename, IMREAD_COLOR) }; + + if (!img.data) + { + cerr << "Failed to load image \'" << filename << "\'" << endl; + return {}; + } + + const auto luts = getLUT(img, refCumHist); + + for (size_t x = 0; x < img.rows; x++) + { + for (size_t y = 0; y < img.cols; y++) + { + for (size_t c = 0; c < 3; c++) + img.at(x, y)[c] = luts[c][img.at(x, y)[c]]; + } + } + + return img; +}