我正在使用手機的攝像頭獲取影像流,然后分析影像以找到其中的 QR 碼(使用 Googles ML Kit)。找到 QR 碼后,我會在影像中獲得 QR 碼的四個角點。我想用一個包含內容的矩形來覆寫它(“容器”在 Flutter 中帶有子項)。
但是,通常攝像頭與二維碼并沒有完全對齊,因此角點不會形成矩形。所以為了用我的矩形覆寫二維碼,我需要轉換我的矩形,使其適合角點。
我的問題是,鑒于四個角點,我如何找出我需要應用于我的內容的轉換矩陣?
uj5u.com熱心網友回復:
這是skiaSkMatrix::setPolyToPoly方法的一個快速埠:
Matrix4? setPolyToPoly(List<Offset> src, List<Offset> dst) {
assert(src.length == 4 && dst.length == 4);
Matrix4? srcMatrix = _poly4Proc(src);
if (srcMatrix == null) {
return null;
}
Matrix4? dstMatrix = _poly4Proc(dst);
if (dstMatrix == null) {
return null;
}
return dstMatrix * Matrix4.inverted(srcMatrix);
}
Matrix4? _poly4Proc(List<Offset> src) {
double a1, a2;
double x0, y0, x1, y1, x2, y2;
x0 = src[2].dx - src[0].dx;
y0 = src[2].dy - src[0].dy;
x1 = src[2].dx - src[1].dx;
y1 = src[2].dy - src[1].dy;
x2 = src[2].dx - src[3].dx;
y2 = src[2].dy - src[3].dy;
/* check if abs(x2) > abs(y2) */
if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
double denom = _ieeeFloatDivide(x1 * y2, x2) - y1;
if (_checkForZero(denom)) {
return null;
}
a1 = (((x0 - x1) * y2 / x2) - y0 y1) / denom;
} else {
double denom = x1 - _ieeeFloatDivide(y1 * x2, y2);
if (_checkForZero(denom)) {
return null;
}
a1 = (x0 - x1 - _ieeeFloatDivide((y0 - y1) * x2, y2)) / denom;
}
/* check if abs(x1) > abs(y1) */
if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
double denom = y2 - _ieeeFloatDivide(x2 * y1, x1);
if (_checkForZero(denom)) {
return null;
}
a2 = (y0 - y2 - _ieeeFloatDivide((x0 - x2) * y1, x1)) / denom;
} else {
double denom = _ieeeFloatDivide(y2 * x1, y1) - x2;
if (_checkForZero(denom)) {
return null;
}
a2 = (_ieeeFloatDivide((y0 - y2) * x1, y1) - x0 x2) / denom;
}
return Matrix4(
a2 * src[3].dx src[3].dx - src[0].dx, a2 * src[3].dy src[3].dy - src[0].dy, 0, a2,
a1 * src[1].dx src[1].dx - src[0].dx, a1 * src[1].dy src[1].dy - src[0].dy, 0, a1,
0, 0, 1, 0,
src[0].dx, src[0].dy, 0, 1,
);
}
double _ieeeFloatDivide(double d0, double d1) => d0 / d1;
bool _checkForZero(double d) => d * d == 0;
示例測驗小部件:
class FooPerspective extends StatefulWidget {
@override
State<FooPerspective> createState() => _FooPerspectiveState();
}
class _FooPerspectiveState extends State<FooPerspective> with TickerProviderStateMixin {
static const src = [
Offset(0, 0),
Offset(100, 0),
Offset(100, 100),
Offset(0, 100),
];
static const dst = [
Offset(100, 200),
Offset(200, 220),
Offset(220, 290),
Offset(120, 300),
];
late final ctrl = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 600),
);
@override
Widget build(BuildContext context) {
return SizedBox.expand(
child: Stack(
children: [
AnimatedBuilder(
animation: ctrl,
builder: (ctx, child) {
final transformedDst = <Offset>[
for (int i = 0; i < 4; i )
Offset.lerp(src[i], dst[i], ctrl.value)!,
];
return Transform(
transform: setPolyToPoly(src, transformedDst) ?? Matrix4.identity(),
child: child,
);
},
child: Container(
width: 100,
height: 100,
padding: const EdgeInsets.all(4),
decoration: const BoxDecoration(
color: Colors.orange,
boxShadow: [BoxShadow(spreadRadius: 1, blurRadius: 6, offset: Offset(3, 3))],
),
child: const Text('Cillum non minim officia excepteur in qui.', textScaleFactor: 1.2),
),
),
Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
onPressed: () {
ctrl.value < 0.5? ctrl.forward() : ctrl.reverse();
},
child: Text('start transition'),
),
),
...dst.map((o) => Positioned(
left: o.dx - 8,
top: o.dy - 8,
width: 16,
height: 16,
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 1),
),
),
)),
],
),
);
}
}
結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/515354.html
標籤:扑数学矩阵几何学转换
上一篇:獲取火箭的軌跡
