summaryrefslogtreecommitdiff
path: root/imagealgos.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'imagealgos.cpp')
-rw-r--r--imagealgos.cpp228
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;
+}