Мы для своего проекта
Krutoscope искали решение проблемы коррекции перспективных искажений при вырезании изображения прямоугольного листа из фотографии этого листа. Везде реализации выпрямления четырёхугольника в прямоугольник попадались только через линейные пропорции! Прям везде, где искали!
И вот, благодаря этому Вашему вопросу, мы (Евгений Берёзкин, Никита Трубкин и я) таки написали на
dart функцию, успешно выбирающую цвета точек для вырезанного листа из оригинальной фотки по координатам углов этого листа, и при этом, кажется, перспективные искажения успешно исправляющую!
import 'package:image/image.dart' as imglib;
class PerspectiveRectifier {
late num a, b, c;
late num a1, b1, c1;
late num d, e, f;
PerspectiveRectifier(imglib.Point topLeft, imglib.Point topRight,
imglib.Point bottomLeft, imglib.Point bottomRight) {
final x1 = topLeft.x;
final y1 = topLeft.y;
final x2 = topRight.x;
final y2 = topRight.y;
final x3 = bottomRight.x;
final y3 = bottomRight.y;
final x4 = bottomLeft.x;
final y4 = bottomLeft.y;
a = ((y4 - y3) * (x1 + x3 - x2 - x4) - (x4 - x3) * (y1 + y3 - y2 - y4)) /
((y4 - y3) * (x2 - x3) - (x4 - x3) * (y2 - y3));
b = (x1 + x3 - x2 - x4 - (x2 - x3) * a) / (x4 - x3);
c = 1;
a1 = x2 * a + x2 - x1;
b1 = x4 * b + x4 - x1;
c1 = x1;
d = y2 * a + y2 - y1;
e = y4 * b + y4 - y1;
f = y1;
}
Offset calculateSourceOffset(Offset relativeTargetOffset) {
return Offset(
(a1 * relativeTargetOffset.dx + b1 * relativeTargetOffset.dy + c1) /
(a * relativeTargetOffset.dx + b * relativeTargetOffset.dy + c),
(d * relativeTargetOffset.dx + e * relativeTargetOffset.dy + f) /
(a * relativeTargetOffset.dx + b * relativeTargetOffset.dy + c));
}
}
imglib.Image copyRectifyWithPerspectiveCorrection(
imglib.Image src, PerspectiveRectifier r, imglib.Image? toImage) {
final dst = toImage ?? imglib.Image.from(src);
for (int y = 0; y < dst.height; ++y) {
for (int x = 0; x < dst.width; ++x) {
final srsOffset =
r.calculateSourceOffset(Offset(x / dst.width, y / dst.height));
final srcPixel =
src.isBoundsSafe(srsOffset.dx.toInt(), srsOffset.dy.toInt())
? src.getPixel(srsOffset.dx.toInt(), srsOffset.dy.toInt())
: src.getColor(0, 0, 0);
dst.setPixel(x, y, srcPixel);
}
}
return dst;
}
Собираюсь сделать PR в
package:image