diff options
Diffstat (limited to 'imagealgos.cpp')
| -rw-r--r-- | imagealgos.cpp | 228 |
1 files changed, 225 insertions, 3 deletions
diff --git a/imagealgos.cpp b/imagealgos.cpp index 3e84155..b4fba4b 100644 --- a/imagealgos.cpp +++ b/imagealgos.cpp @@ -1,5 +1,7 @@ #include "imagealgos.h" +#include <QDebug> + #include <cassert> #include <cstdint> #include <cstring> @@ -14,6 +16,7 @@ // #include <arm_neon.h> +#include "fuck_intel.h" #include "genetic_algos.h" #include "macro.h" @@ -210,7 +213,7 @@ float process_column(uint16_t (&column)[]) } result = (y2 != y1) ? - (img_height - (float(x1) - (float(y1) / (y2 - y1)))) : + (float(x1) - (float(y1) / (y2 - y1))) : std::numeric_limits<float>::quiet_NaN(); @@ -267,11 +270,230 @@ Pixels process_columns(Image &image) // image.pixels[i] = genetic.run().a; // if (i == 0) { - // std::cout << "pixel: " << image.pixels[i] << std::endl; - // } + // std::cout << "pixel: " << image.pixels[i] << std::endl; + // } } stop_timer(process_columns); return result; } + +Pixels& Pixels::operator+=(const Pixels& other) +{ + std::transform(std::execution::par, + pixels.begin(), pixels.end(), + other.pixels.begin(), + pixels.begin(), + // [](auto& toAdd) { return dst += src; }); + std::plus<>()); + + return *this; +} + +Pixels& Pixels::operator/=(const float divider) +{ + std::for_each(std::execution::par_unseq, + pixels.begin(), pixels.end(), + [divider](auto& pixel) { pixel /= divider; }); + + return *this; +} + +QList<QLineF> pixelsToLines(const Pixels &rawProfile) +{ + const auto& pixels = rawProfile.pixels; + QList<QPointF> points { pixels.size() }; + + for (int i = 0; i < pixels.size(); ++i) + { + points[i] = { qreal(i) - img_width / 2, pixels.at(i) }; + } + + // qDebug() << "mid points" << points.mid(points.count() - 3, 6); + + return pointsToLines(std::move(points)); +} + +QList<QLineF> pointsToLines(const QList<QPointF> &points) +{ + constexpr double maxDistanceFromLine { 3 }; + constexpr double minLineLength { 10 }; + + QList<int> lineAnchors { 0, points.size() - 1 }; + + auto vecLength = [](const QPointF& vector) { + return std::hypot(vector.x(), vector.y()); + }; + + auto distanceToLine = [vecLength](const QPointF& point, const QLineF& line) { + // const auto d1 = point - line.p1(); + // const auto d2 = line.p2() - line.p1(); + + // const auto norm = vecLength(d2); + // qDebug() << "norm" << norm; + + // if (norm <= std::numeric_limits<double>::epsilon()) + // { + // qDebug() << "AAAAAAAAAAAAAAAAAA"; + // return vecLength(d1); + // } + + // const auto result = std::fabs(d1.x() * d2.y() - d1.y() * d2.x()) / norm; + + // if (!qFuzzyIsNull(result)) + // { + // qDebug() << "NOT NULL" << result << point << line; + // } + + // return result; + // transform to loocal coordinates system (0,0) - (lx, ly) + QPointF p1 = line.p1(); + QPointF p2 = line.p2(); + const auto& p = point; + qreal x = p.x() - p1.x(); + qreal y = p.y() - p1.y(); + qreal x2 = p2.x() - p1.x(); + qreal y2 = p2.y() - p1.y(); + + // if line is a point (nodes are the same) => + // just return distance between point and one line node + qreal norm = sqrt(x2*x2 + y2*y2); + if (norm <= std::numeric_limits<int>::epsilon()) + return sqrt(x*x + y*y); + + // distance + // qDebug() << "dist" << fabs(x*y2 - y*x2) / norm << point << line; + return fabs(x*y2 - y*x2) / norm; + }; + + // for (const auto& p : points) + // { + // qDebug() << "\t" << p; + // } + + for (int i = 0; i < lineAnchors.count() - 1; ++i) + { + const auto &lineFirst = i; + const auto &lineLast = i + 1; + const auto& leftPointIdx = lineAnchors.at(lineFirst); + const auto& rightPointIdx = lineAnchors.at(lineLast); + + if (rightPointIdx - leftPointIdx < 2) + { + continue; + } + + const QLineF line { points.at(leftPointIdx), points.at(rightPointIdx) }; + + const auto farthest = std::max_element( + // std::execution::par_unseq, + points.cbegin() + leftPointIdx + 1, + points.cbegin() + rightPointIdx - 1, + [line, distanceToLine](const QPointF& a, const QPointF& b) { + return distanceToLine(a, line) < distanceToLine(b, line); + }); + + // qDebug() << "farthest point" << distanceToLine(*farthest, line); + // qDebug() << "farthest dist" << distanceToLine(*farthest, line); + // qDebug() << "that's from line" << line; + + if (distanceToLine(*farthest, line) > maxDistanceFromLine) + { + lineAnchors.insert(i + 1, farthest - points.cbegin()); + --i; + // qDebug() << "I'm here" << i; + continue; + } + } + + struct LineAB + { + double a { std::numeric_limits<double>::quiet_NaN() }; + double b { std::numeric_limits<double>::quiet_NaN() }; + + LineAB(const QList<QPointF>& points) { + if (points.isEmpty()) + { + return; + } + + double sumX { 0 }; + double sumY { 0 }; + double sumXY { 0 }; + double sumXX { 0 }; + + // FIXME: validate + // for (const auto& point : points) + const int delta = points.count() * 0.15; + for (int i = delta; i < points.count() - delta; ++i) + { + const auto& point = points.at(i); + sumX += point.x(); + sumY += point.y(); + sumXY += point.x() * point.y(); + sumXX += point.x() * point.x(); + } + + // sumX /= points.count(); + // sumY /= points.count(); + // sumXY /= points.count(); + // sumXX /= points.count(); + + const int n = points.count() - delta * 2; + Q_ASSERT_X(n > 0, Q_FUNC_INFO, "n <= 0"); + + a = (n * sumXY - sumX * sumY) / + (n * sumXX - sumX * sumX); + b = (sumY - a * sumX) / n; + } + }; + + // auto pointsToLineAB = + + // qDebug() << "line anchors count is" << lineAnchors.count(); + + constexpr bool useLsd = true; + + QList<QLineF> result { lineAnchors.length() - 1 }; + + for (int i = 0; i < lineAnchors.count() - 1; ++i) + { + const auto& leftPointIdx = lineAnchors.at(i); + const auto& rightPointIdx = lineAnchors.at(i + 1); + + QPointF leftPoint = points.at(leftPointIdx); + QPointF rightPoint = points.at(rightPointIdx); + + LineAB lineAB(points.mid(leftPointIdx, rightPointIdx - leftPointIdx)); + + leftPoint.setY(lineAB.a * leftPoint.x() + lineAB.b); + rightPoint.setY(lineAB.a * rightPoint.x() + lineAB.b); + + if (useLsd) + result[i] = QLineF{ std::move(leftPoint), std::move(rightPoint) }; + else + result[i] = QLineF{ points.at(lineAnchors.at(i)), points.at(lineAnchors.at(i + 1)) }; + } + + if (useLsd) + { + for (int i = 0; i < result.count() - 1; ++i) + { + auto& lineA = result[i]; + auto& lineB = result[i + 1]; + + QPointF intersectionPoint {}; + + if (lineA.intersects(lineB, &intersectionPoint) != QLineF::NoIntersection) + { + lineA.setP2(intersectionPoint); + lineB.setP1(intersectionPoint); + } + } + } + + // qDebug() << result; + + return result; +} |
