diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2025-01-14 18:04:32 +0100 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2025-01-14 18:04:32 +0100 |
| commit | 38acf876313c9bf28e41acd8bc29d6115c1e9285 (patch) | |
| tree | dc59c6c26006f740e1990150f920f4032734fc13 /src/calibration.cpp | |
| parent | 201d98f63131242bb8871ed0c4a3ae9ebd4ef030 (diff) | |
refactoring
Diffstat (limited to 'src/calibration.cpp')
| -rw-r--r-- | src/calibration.cpp | 174 |
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; |
