diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2026-07-15 10:13:10 +0200 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2026-07-15 10:13:10 +0200 |
| commit | 2aefb6902465c3c8a313f95bb1b7d9a80fe4c52a (patch) | |
| tree | 525cafbc1a9f38df2f0d2ebe6fe9fd206e5f30d0 /src/calibration.cpp | |
| parent | 169ddcb09cd26fa0a685f691f63b49e70e1be93b (diff) | |
in the middle of non-linear pixels debuggingconflicting_master
Diffstat (limited to 'src/calibration.cpp')
| -rw-r--r-- | src/calibration.cpp | 189 |
1 files changed, 157 insertions, 32 deletions
diff --git a/src/calibration.cpp b/src/calibration.cpp index 3462565..6e8f695 100644 --- a/src/calibration.cpp +++ b/src/calibration.cpp @@ -4,6 +4,7 @@ #include <execution> #include <iostream> +#include <numeric> #include <QDebug> #include <QDir> @@ -15,7 +16,7 @@ #include "imagealgos.h" -bool openCalibrationTable(const QString &filename, const CalibrationTablePtr table) +bool op::openCalibrationTable(const QString &filename, const op::CalibrationTablePtr table) { QFile f(filename); @@ -26,9 +27,9 @@ bool openCalibrationTable(const QString &filename, const CalibrationTablePtr tab return false; } - auto bytes = f.read((char*) table.data(), sizeof(CalibrationTable)); + auto bytes = f.read((char *) table.data(), sizeof(op::CalibrationTable)); - if (bytes != sizeof(CalibrationTable)) { + if (bytes != sizeof(op::CalibrationTable)) { qWarning() << "cannot read calibration table from" << filename << bytes; if (f.error()) { @@ -44,13 +45,14 @@ bool openCalibrationTable(const QString &filename, const CalibrationTablePtr tab // qDebug() << "calibration column mid:" << col[640]; // } + qDebug() << "calibration table opened:" << filename; + return true; } -bool dump( - const CalibrationTablePtr& table, const QString& filename) +bool op::dump(const op::CalibrationTablePtr &table, const QString &filename) { - qDebug() << Q_FUNC_INFO << "size is" << sizeof(CalibrationTable); + qDebug() << Q_FUNC_INFO << "size is" << sizeof(op::CalibrationTable); QFile f(filename); @@ -61,10 +63,9 @@ bool dump( return false; } - const auto written = f.write((const char*) table.data(), - sizeof(CalibrationTable)); + const auto written = f.write((const char *) table.data(), sizeof(op::CalibrationTable)); - if (written != sizeof(CalibrationTable) || !f.flush()) { + if (written != sizeof(op::CalibrationTable) || !f.flush()) { qWarning() << Q_FUNC_INFO << "cannot write" << filename << ":" << f.errorString(); return false; @@ -73,12 +74,11 @@ bool dump( return true; } -void interpolate(const CalibrationTablePtr table) +void op::interpolate(const op::CalibrationTablePtr table) { - std::for_each(std::execution::par, - table->begin(), - table->end(), - [](auto& column) { interpolate(column); }); + std::for_each(std::execution::par, table->begin(), table->end(), [](auto &column) { + op::interpolate(column); + }); // for (size_t i = 9471; i < 9472; i++) { // std::cout << __func__ << ": row #" << i << ": "; @@ -107,8 +107,7 @@ void interpolate(const CalibrationTablePtr table) // } } -void interpolate( - CalibrationColumn& column) +void op::interpolate(op::CalibrationColumn &column) { size_t start{0}; auto& c = column; @@ -150,8 +149,7 @@ void interpolate( } } -QImage calibrationTableToImage( - const CalibrationTablePtr& calibrationTable) +QImage op::calibrationTableToImage(const op::CalibrationTablePtr &calibrationTable) { QImage result(QSize(calibrationTable->size(), calibrationTable->at(0).size()), @@ -190,14 +188,12 @@ QImage calibrationTableToImage( } qDebug() << "not null count" << notNull << "of" - << sizeof(CalibrationTable) / - sizeof(calibrationTable->at(0).at(0)); + << sizeof(op::CalibrationTable) / sizeof(calibrationTable->at(0).at(0)); return result; } -QList<Pixels> filter( - const QList<Pixels>& rawProfiles) +QList<Pixels> op::filter(const QList<Pixels> &rawProfiles) { QList<Pixels> result; @@ -225,9 +221,9 @@ QList<Pixels> filter( return result; } -bool calibrateZ(const QList<Pixels> &rawProfiles, - const uint32_t &stepsPerMm, - CalibrationTablePtr table) +bool op::calibrateZ(const QList<Pixels> &rawProfiles, + const uint32_t &stepsPerMm, + op::CalibrationTablePtr table) { for (const auto &rawProfile : rawProfiles) { const float positionMm{float(rawProfile.counters.encoderPosition) / @@ -241,7 +237,7 @@ bool calibrateZ(const QList<Pixels> &rawProfiles, uint16_t(pixelValue * discretesInRage / img_height)}; // TODO: move this validation to some better place - if (Q_UNLIKELY(discretePixelValue >= calibrationColumnHeight)) { + if (Q_UNLIKELY(discretePixelValue >= op::calibrationColumnHeight)) { std::cerr << __func__ << ":/tinvalid discrete value. col: " << columnIdx << ", val: " << pixelValue << std::endl; @@ -257,12 +253,15 @@ bool calibrateZ(const QList<Pixels> &rawProfiles, return true; } -bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) +bool op::calibrateX(const QList<Pixels> &rawProfiles, op::CalibrationTablePtr table) { // TODO: move to settings constexpr double triangleBaseMm{8.}; + int i{-1}; + for (const auto &rawProfile : rawProfiles) { + ++i; const auto& pixels = rawProfile.pixels; auto lines = pixelsToLines(rawProfile); @@ -278,6 +277,7 @@ bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) xAnchors.begin(), [](const auto& l) { return l.x1(); }); xAnchors.last() = lines.last().x2(); + // qDebug() << "anchors (discretes):" << xAnchors; auto centralAnchorIt = std::min_element(std::execution::par_unseq, xAnchors.constBegin(), @@ -299,6 +299,13 @@ bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) auto xAnchorIt = xAnchors.constBegin() + 1; auto xAnchorMmIt = xAnchorsMm.constBegin() + 1; + // qDebug() << "anchors (mm):" << xAnchors; + + if (rawProfile.counters.encoderPosition > 6000) { + qt_noop(); + } + + std::array<uint16_t, img_width> dl = {uint16_t{0}}; for (size_t columnIdx = 0; columnIdx < pixels.size(); ++columnIdx) { // skip points with to the left from left line and to the right from @@ -335,7 +342,7 @@ bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) uint16_t(pixelValue * discretesInRage / img_height)}; // TODO: move this validation to some better place - if (Q_UNLIKELY(discretePixelValue >= calibrationColumnHeight)) { + if (Q_UNLIKELY(discretePixelValue >= op::calibrationColumnHeight)) { std::cerr << __func__ << ":/tinvalid discrete value. col: " << columnIdx << ", val: " << pixelValue << std::endl; @@ -348,15 +355,24 @@ bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) const auto xRelative = float(columnX - xLeft) / xLineLen; const auto xMmValue = xLeftMm + xRelative * (triangleBaseMm / 2.); + // TODO: check if value exists (*table)[columnIdx][discretePixelValue] = xMmValue; + dl[columnIdx] = discretePixelValue; } + + // const auto avg_dpv = std::accumulate(dl.cbegin(), dl.cend(), uint64_t{0}) / img_width; + // const auto avg_p = std::accumulate(pixels.cbegin(), pixels.cend(), double{0.}) / img_width; + // std::cout << avg_dpv << '/' << avg_p << std::endl; + // qDebug() << rawProfile; } + std::cout << std::endl; + return true; } -void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrationPixels, - const DumpFormat format) +void op::dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrationPixels, + const op::DumpFormat format) { const auto &rawProfiles = calibrationPixels; // std::vector<Pixels> rawProfiles; @@ -381,7 +397,7 @@ void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrat // TODO: move out of `for` loop // TODO: use switch, or remove enum and create a separate function - if (format == DumpFormat::Json) { + if (format == op::DumpFormat::Json) { QFile f{filepath}; if (!f.open(QFile::WriteOnly)) { @@ -417,7 +433,7 @@ void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrat } qDebug() << "file written: " << f.fileName(); - } else if (format == DumpFormat::Binary) { + } else if (format == op::DumpFormat::Binary) { if (!rawProfile->save(filepath)) { return; } @@ -426,3 +442,112 @@ void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrat qDebug() << "dump finished"; } + +bool areAllEncPosIdentical(const std::vector<Pixels> &rawProfiles) +{ + if (rawProfiles.empty()) { + return false; + } + + if (rawProfiles.size() == 1) { + return true; + } + + // const auto equalEncPos = [](const Pixels &a, const Pixels &b) { + // return a.counters.encoderPosition == b.counters.encoderPosition; + // }; + const auto nonEqualEncPos = [](const Pixels &a, const Pixels &b) { + return a.counters.encoderPosition != b.counters.encoderPosition; + }; + + return std::ranges::adjacent_find(rawProfiles, nonEqualEncPos) == rawProfiles.end(); +} + +std::optional<Pixels> op::avgFilterAtPos(const std::vector<Pixels> &rawProfiles) +{ + if (rawProfiles.empty()) { + return std::nullopt; + } + + if (rawProfiles.size() == 1) { + return rawProfiles.front(); + } + + if (!areAllEncPosIdentical(rawProfiles)) { + return std::nullopt; + } + + Pixels sum; + sum.counters = rawProfiles.front().counters; + + // TODO: think about std::accumulate + // const auto tmp = std::accumulate(rawProfiles.begin(), rawProfiles.end(), Pixels{}); + + for (const auto &rp : rawProfiles) { + sum += rp; + } + + sum /= rawProfiles.size(); + + return sum; +} + +std::optional<Pixels> op::medianFilterAtPos(const std::vector<Pixels> &rawProfiles) +{ + const auto &rps = rawProfiles; + + if (rps.empty()) { + return std::nullopt; + } + + if (rps.size() == 1) { + return rps.front(); + } + + if (!areAllEncPosIdentical(rps)) { + return std::nullopt; + } + + using pixel_t = decltype(Pixels::pixels)::value_type; + // std::array<std::vector<pixel_t>, img_width> forMedian; + + Pixels result; + + for (size_t i{0}; i < img_width; ++i) { + std::vector<pixel_t> pixelsAtI; + pixelsAtI.reserve(rps.size()); + + for (const auto &rp : rps) { + const auto &p = rp.pixels.at(i); + + if (qFuzzyIsNull(p) || qIsNaN(p)) { + continue; + } + pixelsAtI.push_back(p); + } + + // result.pixels.at(i) = pixelsAtI.empty() ? 0 : + if (pixelsAtI.empty()) { + continue; + } + + if (pixelsAtI.size() == 1) { + result.pixels.at(i) = pixelsAtI.front(); + continue; + } + + std::sort(std::execution::par_unseq, pixelsAtI.begin(), pixelsAtI.end()); + + if (pixelsAtI.size() % 2 == 1) { + result.pixels.at(i) = pixelsAtI.at(pixelsAtI.size() / 2); + } else { + result.pixels.at(i) = (pixelsAtI.at(pixelsAtI.size() / 2 - 1) + + pixelsAtI.at(pixelsAtI.size() / 2)) + / 2; + } + } + + result.counters = rps.front().counters; + + return result; +} |
