summaryrefslogtreecommitdiff
path: root/src/calibration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/calibration.cpp')
-rw-r--r--src/calibration.cpp174
1 files changed, 64 insertions, 110 deletions
diff --git a/src/calibration.cpp b/src/calibration.cpp
index ff37e73..7fcdbcc 100644
--- a/src/calibration.cpp
+++ b/src/calibration.cpp
@@ -13,7 +13,8 @@
#include "imagealgos.h"
-bool openCalibrationTable(const QString& filename, CalibrationTablePtr& table)
+bool openCalibrationTable(
+ const QString& filename, CalibrationTablePtr& table)
{
QFile f(filename);
@@ -46,7 +47,8 @@ bool openCalibrationTable(const QString& filename, CalibrationTablePtr& table)
return true;
}
-bool dump(const CalibrationTablePtr& table, const QString& filename)
+bool dump(
+ const CalibrationTablePtr& table, const QString& filename)
{
qDebug() << Q_FUNC_INFO << "size is" << sizeof(CalibrationTable);
@@ -71,7 +73,8 @@ bool dump(const CalibrationTablePtr& table, const QString& filename)
return true;
}
-void interpolate(CalibrationTablePtr& table)
+void interpolate(
+ CalibrationTablePtr& table)
{
std::for_each(std::execution::par,
table->begin(),
@@ -105,7 +108,8 @@ void interpolate(CalibrationTablePtr& table)
// }
}
-void interpolate(CalibrationColumn& column)
+void interpolate(
+ CalibrationColumn& column)
{
size_t start{0};
auto& c = column;
@@ -147,7 +151,8 @@ void interpolate(CalibrationColumn& column)
}
}
-QImage calibrationTableToImage(const CalibrationTablePtr& calibrationTable)
+QImage calibrationTableToImage(
+ const CalibrationTablePtr& calibrationTable)
{
QImage result(QSize(calibrationTable->size(),
calibrationTable->at(0).size()),
@@ -185,28 +190,27 @@ QImage calibrationTableToImage(const CalibrationTablePtr& calibrationTable)
}
qDebug() << "not null count" << notNull << "of"
- << sizeof(CalibrationTable)
- / sizeof(calibrationTable->at(0).at(0));
+ << sizeof(CalibrationTable) /
+ sizeof(calibrationTable->at(0).at(0));
return result;
}
-QList<Pixels> filter(const QList<Pixels>& rawProfiles)
+QList<Pixels> filter(
+ const QList<Pixels>& rawProfiles)
{
QList<Pixels> result;
QList<Pixels>::const_iterator it = rawProfiles.constBegin();
- while (it != rawProfiles.constEnd())
- {
+ while (it != rawProfiles.constEnd()) {
Pixels sum = *it;
size_t count{1};
++it;
while (it != rawProfiles.constEnd() &&
- it->counters.encoderPosition == sum.counters.encoderPosition)
- {
+ it->counters.encoderPosition == sum.counters.encoderPosition) {
sum += *it;
++count;
++it;
@@ -219,127 +223,79 @@ QList<Pixels> filter(const QList<Pixels>& rawProfiles)
return result;
}
-CalibrationTablePtr calibrateZ(const QList<Pixels>& rawProfiles,
- const uint32_t& stepsPerMm)
+CalibrationTablePtr calibrateZ(
+ const QList<Pixels>& rawProfiles, const uint32_t& stepsPerMm)
{
CalibrationTablePtr result{new CalibrationTable{{0}}};
for (const auto& rawProfile : rawProfiles) {
- // std::cout << "calibration: pos is "
- // << rawProfile.counters.encoderPosition << std::endl;
- const float positionMm{float(rawProfile.counters.encoderPosition)
- / float(stepsPerMm)};
-
- if (positionMm >= 200) {
- qWarning() << "got invalid calibration distance:" << positionMm;
- qWarning() << "encoder position:"
- << rawProfile.counters.encoderPosition;
- exit(EXIT_FAILURE);
- }
+ const float positionMm{float(rawProfile.counters.encoderPosition) /
+ float(stepsPerMm)};
const auto& pixels = rawProfile.pixels;
- // printPixels(pixels);
- // static size_t counter { 0 };
- // qDebug() << "calibrated" << counter++;
- const float pos = rawProfile.counters.encoderPosition;
- const float divider = stepsPerMm;
- // std::cout << pos << " " << divider << " " << pos / divider <<
- // std::endl; std::cout << std::setw(5) <<
- // rawProfile.counters.encoderPosition
- // << std::setw(5) << requested_params.stepsPerMm
- // << std::setw(8) << positionMm
- // << std::setw(8) <<
- // float(rawProfile.counters.encoderPosition) /
- // float(requested_params.stepsPerMm)
- // << ": ";
for (size_t columnIdx = 0; columnIdx < pixels.size(); ++columnIdx) {
const auto& pixelValue = pixels.at(columnIdx);
-
- // float[0, img_height] -> uint16_t[0, calibrationColumnHeight]
const uint16_t discretePixelValue{
uint16_t(pixelValue * discretesInRage / img_height)};
- Q_ASSERT_X(discretePixelValue > 0
- && discretePixelValue < calibrationColumnHeight,
- Q_FUNC_INFO,
- ("got ivalid discrete value "
- + QString::number(discretePixelValue)
- + ". pixelValues is " + QString::number(pixelValue)
- + ". calc result is "
- + QString::number(pixelValue * discretesInRage
- / img_height))
- .toStdString()
- .c_str());
+ // TODO: move this validation to some better place
+ if (Q_UNLIKELY(discretePixelValue >= calibrationColumnHeight)) {
+ std::cerr << __func__
+ << ":/tinvalid discrete value. col: " << columnIdx
+ << ", val: " << pixelValue << std::endl;
- // auto& calibrationColumn = result[columnIdx];
- auto& calibrationColumn = (*result)[columnIdx];
+ return {};
+ }
+ auto& calibrationColumn = (*result)[columnIdx];
calibrationColumn[discretePixelValue] = positionMm;
-
- // if (columnIdx >= ((img_width - 10) / 2) &&
- // columnIdx < img_width - ((img_width - 10) / 2))
- // {
- // std::cout << discretePixelValue << ";";
- // }
}
-
- // std::cout << std::endl << std::flush;
}
return result;
- // TODO: try something interesting
- // return {};
}
-CalibrationTablePtr calibrateX(const QList<Pixels>& rawProfiles)
+CalibrationTablePtr calibrateX(
+ const QList<Pixels>& rawProfiles)
{
+ // TODO: move to settings
+ constexpr double triangleBaseMm{8.};
CalibrationTablePtr result{new CalibrationTable{{0}}};
- static size_t tmp_counter = 0;
-
for (const auto& rawProfile : rawProfiles) {
const auto& pixels = rawProfile.pixels;
auto lines = pixelsToLines(rawProfile);
- tmp_counter++;
-
- Q_ASSERT_X(lines.count() > 2, Q_FUNC_INFO, "no lines");
-
- if (tmp_counter == 9471) {
- for (const auto& l : lines) {
- qDebug() << "line:" << l;
- }
+ if (lines.count() < 2) {
+ continue;
}
+ // x coords of line endings - [l1.p1.x; lN.p2.x]
QList<double> xAnchors(lines.size() + 1);
-
std::transform(std::execution::par_unseq,
lines.constBegin(),
lines.constEnd(),
xAnchors.begin(),
[](const auto& l) { return l.x1(); });
-
xAnchors.last() = lines.last().x2();
- constexpr double triangleHeightMm{5.};
- constexpr double triangleBaseMm{8.};
-
- auto nearestAnchorToX0 = std::min_element(std::execution::par_unseq,
- xAnchors.constBegin(),
- xAnchors.constEnd(),
- [](const auto& a,
- const auto& b) {
- return std::abs(a)
- < std::abs(b);
- });
+ auto centralAnchorIt = std::min_element(std::execution::par_unseq,
+ xAnchors.constBegin(),
+ xAnchors.constEnd(),
+ [](const auto& a,
+ const auto& b) {
+ return std::abs(a) <
+ std::abs(b);
+ });
- int nearestAnchorToX0Idx = nearestAnchorToX0 - xAnchors.constBegin();
+ int centralAnchorIdx = centralAnchorIt - xAnchors.constBegin();
+ // convert line image coords to mm coords
QList<double> xAnchorsMm(xAnchors.count());
for (int i = 0; i < xAnchors.size(); ++i) {
- xAnchorsMm[i] = (i - nearestAnchorToX0Idx) * triangleBaseMm / 2.;
+ xAnchorsMm[i] = (i - centralAnchorIdx) * triangleBaseMm / 2.;
}
auto xAnchorIt = xAnchors.constBegin() + 1;
@@ -349,17 +305,23 @@ CalibrationTablePtr calibrateX(const QList<Pixels>& rawProfiles)
// skip points with to the left from left line and to the right from
// right line
const auto columnX = int(columnIdx) - int(img_width / 2);
+
if (columnX < xAnchors.first() || columnX > xAnchors.last()) {
continue;
}
- if (columnX > *xAnchorIt) {
+ // if [...(anchor-1)...(anchor)...(column)...]
+ // then use next anchor to have [...(anchor-1)...(column)...anchor...]
+ if (*xAnchorIt < columnX) {
++xAnchorIt;
++xAnchorMmIt;
}
const auto xLeft = *(xAnchorIt - 1);
const auto xRight = *(xAnchorIt);
+ // there could be points which don't belong to any lines, because
+ // some real lines can be too short and will be ignored by
+ // `pixelsToLines`. e.g. the most left/right lines. skip such points
if (columnX < xLeft || columnX > xRight) {
if (rawProfile.counters.encoderPosition >= 0) {
qWarning()
@@ -372,37 +334,29 @@ CalibrationTablePtr calibrateX(const QList<Pixels>& rawProfiles)
const uint16_t discretePixelValue{
uint16_t(pixelValue * discretesInRage / img_height)};
- Q_ASSERT_X(discretePixelValue > 0
- && discretePixelValue < calibrationColumnHeight,
- Q_FUNC_INFO,
- ("got ivalid discrete value "
- + QString::number(discretePixelValue)
- + ". pixelValues is " + QString::number(pixelValue)
- + ". calc result is "
- + QString::number(pixelValue * discretesInRage
- / img_height))
- .toStdString()
- .c_str());
+ // TODO: move this validation to some better place
+ if (Q_UNLIKELY(discretePixelValue >= calibrationColumnHeight)) {
+ std::cerr << __func__
+ << ":/tinvalid discrete value. col: " << columnIdx
+ << ", val: " << pixelValue << std::endl;
+ return {};
+ }
+ // use value interpolated between line endings (anchors)
const auto xLineLen = xRight - xLeft;
const auto xLeftMm = *(xAnchorMmIt - 1);
const auto xRelative = float(columnX - xLeft) / xLineLen;
const auto xMmValue = xLeftMm + xRelative * (triangleBaseMm / 2.);
- auto& calibrationColumn = (*result)[columnIdx];
-
- if (tmp_counter == 9471) {
- qDebug() << "calibration value" << columnIdx
- << discretePixelValue << xMmValue;
- }
- calibrationColumn[discretePixelValue] = xMmValue;
+ (*result)[columnIdx][discretePixelValue] = xMmValue;
}
}
return result;
}
-void dumpCalibrationPixels(std::vector<Pixels>&& calibrationPixels)
+void dumpCalibrationPixels(
+ std::vector<Pixels>&& calibrationPixels)
{
std::vector<Pixels> rawProfiles;