summaryrefslogtreecommitdiff
path: root/src/calibration.cpp
diff options
context:
space:
mode:
authorNikita Kostovsky <nikita@kostovsky.me>2026-07-15 10:13:10 +0200
committerNikita Kostovsky <nikita@kostovsky.me>2026-07-15 10:13:10 +0200
commit2aefb6902465c3c8a313f95bb1b7d9a80fe4c52a (patch)
tree525cafbc1a9f38df2f0d2ebe6fe9fd206e5f30d0 /src/calibration.cpp
parent169ddcb09cd26fa0a685f691f63b49e70e1be93b (diff)
in the middle of non-linear pixels debuggingconflicting_master
Diffstat (limited to 'src/calibration.cpp')
-rw-r--r--src/calibration.cpp189
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;
+}