mirror of
https://github.com/flutter/holobooth.git
synced 2025-08-06 14:50:05 +08:00
feat: rotating head calculation sample
This commit is contained in:
@ -38,10 +38,6 @@ class _LandmarksRotatingFaceViewState
|
|||||||
void _onCameraReady(CameraController cameraController) {
|
void _onCameraReady(CameraController cameraController) {
|
||||||
setState(() => _cameraController = cameraController);
|
setState(() => _cameraController = cameraController);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => _queryVideoElement());
|
WidgetsBinding.instance.addPostFrameCallback((_) => _queryVideoElement());
|
||||||
Future.delayed(
|
|
||||||
Duration(seconds: 10),
|
|
||||||
() => _cameraController!.pausePreview(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _queryVideoElement() {
|
void _queryVideoElement() {
|
||||||
@ -266,53 +262,28 @@ class _ZAxisArrowsIllustration extends StatelessWidget {
|
|||||||
_ZAxisArrowsIllustration({
|
_ZAxisArrowsIllustration({
|
||||||
required this.face,
|
required this.face,
|
||||||
required this.offset,
|
required this.offset,
|
||||||
}) {
|
});
|
||||||
// Computing the face rotation is a feature is still in development:
|
|
||||||
// https://github.com/tensorflow/tfjs/issues/3835#issuecomment-1109111171
|
|
||||||
|
|
||||||
final leftCheeck = face.keypoints[127];
|
|
||||||
final rightCheeck = face.keypoints[356];
|
|
||||||
final nose = face.keypoints[6];
|
|
||||||
|
|
||||||
// final distanceToNose = Vector3(
|
|
||||||
// (nose.x - leftCheeck.x).toDouble(),
|
|
||||||
// (nose.y - leftCheeck.y).toDouble(),
|
|
||||||
// (nose.z! - leftCheeck.z!).toDouble(),
|
|
||||||
// );
|
|
||||||
// final distanceBetweenCheecks = Vector3(
|
|
||||||
// (rightCheeck.x - leftCheeck.x).toDouble(),
|
|
||||||
// (rightCheeck.y - leftCheeck.y).toDouble(),
|
|
||||||
// (rightCheeck.z! - leftCheeck.z!).toDouble(),
|
|
||||||
// );
|
|
||||||
// final perpendicular = distanceToNose.cross(distanceBetweenCheecks);
|
|
||||||
|
|
||||||
// _vectorX = distanceBetweenCheecks.normalized();
|
|
||||||
// _vectorY = perpendicular.normalized();
|
|
||||||
// _vectorZ = _vectorX.cross(_vectorY).normalized();
|
|
||||||
final bottomX = (rightCheeck.x + leftCheeck.x) / 2;
|
|
||||||
final bottomY = (rightCheeck.y + leftCheeck.y) / 2;
|
|
||||||
_degree = math.atan((nose.y - bottomY) / (nose.x - bottomX));
|
|
||||||
}
|
|
||||||
|
|
||||||
final tf.Face face;
|
final tf.Face face;
|
||||||
|
|
||||||
final Offset offset;
|
final Offset offset;
|
||||||
|
|
||||||
// late final Vector3 _vectorX;
|
|
||||||
// late final Vector3 _vectorY;
|
|
||||||
// late final Vector3 _vectorZ;
|
|
||||||
late final double _degree;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const length = 100.0;
|
const length = 100.0;
|
||||||
|
final rotation = face.rotation().normalized() * 2;
|
||||||
|
|
||||||
return ZIllustration(
|
return ZIllustration(
|
||||||
children: [
|
children: [
|
||||||
ZPositioned(
|
ZPositioned(
|
||||||
translate: ZVector.only(x: offset.dx, y: offset.dy),
|
translate: ZVector.only(x: offset.dx, y: offset.dy),
|
||||||
rotate: ZVector.only(x: _degree),
|
rotate: ZVector.only(
|
||||||
|
x: -rotation.z,
|
||||||
|
y: -rotation.x,
|
||||||
|
// z: -rotation.y,
|
||||||
|
),
|
||||||
child: ZGroup(
|
child: ZGroup(
|
||||||
|
sortMode: SortMode.stack,
|
||||||
children: [
|
children: [
|
||||||
ZShape(
|
ZShape(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
@ -346,35 +317,61 @@ class _ZAxisArrowsIllustration extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix3 _calculateRotationMatrix(tf.Face face) {
|
extension on tf.Face {
|
||||||
// Math calculations extractred from the following pull request, see https://github.com/tensorflow/tfjs-models/pull/844/files/.
|
Vector3 rotation() {
|
||||||
final leftCheeck = face.keypoints[127];
|
final leftCheeck = keypoints[127];
|
||||||
final rightCheeck = face.keypoints[356];
|
final rightCheeck = keypoints[356];
|
||||||
final nose = face.keypoints[6];
|
final nose = keypoints[6];
|
||||||
|
|
||||||
final distanceToNose = Vector3(
|
final leftCheeckVector = Vector3(
|
||||||
(nose.x - leftCheeck.x).toDouble(),
|
leftCheeck.x.toDouble(),
|
||||||
(nose.y - leftCheeck.y).toDouble(),
|
leftCheeck.y.toDouble(),
|
||||||
(nose.z! - leftCheeck.z!).toDouble(),
|
leftCheeck.z?.toDouble() ?? 0,
|
||||||
);
|
);
|
||||||
final distanceBetweenCheecks = Vector3(
|
final rightCheeckVector = Vector3(
|
||||||
(rightCheeck.x - leftCheeck.x).toDouble(),
|
rightCheeck.x.toDouble(),
|
||||||
(rightCheeck.y - leftCheeck.y).toDouble(),
|
rightCheeck.y.toDouble(),
|
||||||
(rightCheeck.z! - leftCheeck.z!).toDouble(),
|
rightCheeck.z?.toDouble() ?? 0,
|
||||||
|
);
|
||||||
|
final noseVector = Vector3(
|
||||||
|
nose.x.toDouble(),
|
||||||
|
nose.y.toDouble(),
|
||||||
|
nose.z?.toDouble() ?? 0,
|
||||||
);
|
);
|
||||||
final perpendicular = distanceToNose.cross(distanceBetweenCheecks);
|
|
||||||
|
|
||||||
final vectorX = distanceBetweenCheecks.normalized();
|
return _equationOfAPlane(leftCheeckVector, rightCheeckVector, noseVector);
|
||||||
final vectorY = perpendicular.normalized();
|
|
||||||
final vectorZ = vectorX.cross(vectorY).normalized();
|
// final vector1 = leftCheeckVector - rightCheeckVector;
|
||||||
return Matrix3.zero()
|
// final vector2 = noseVector - rightCheeckVector;
|
||||||
..row0.x = vectorX.x
|
|
||||||
..row0.y = vectorY.x
|
// return vector1.cross(vector2).normalized();
|
||||||
..row0.z = vectorZ.x
|
}
|
||||||
..row1.x = vectorX.y
|
}
|
||||||
..row1.y = vectorY.y
|
|
||||||
..row1.z = vectorZ.y
|
Vector3 _equationOfAPlane(Vector3 x, Vector3 y, Vector3 z) {
|
||||||
..row2.x = vectorX.z
|
final x1 = x.x;
|
||||||
..row2.y = vectorY.z
|
final y1 = x.y;
|
||||||
..row2.z = vectorZ.z;
|
final z1 = x.z;
|
||||||
|
final x2 = y.x;
|
||||||
|
final y2 = y.y;
|
||||||
|
final z2 = y.z;
|
||||||
|
final x3 = z.x;
|
||||||
|
final y3 = z.y;
|
||||||
|
final z3 = z.z;
|
||||||
|
|
||||||
|
final a1 = x2 - x1;
|
||||||
|
final b1 = y2 - y1;
|
||||||
|
final c1 = z2 - z1;
|
||||||
|
final a2 = x3 - x1;
|
||||||
|
final b2 = y3 - y1;
|
||||||
|
final c2 = z3 - z1;
|
||||||
|
|
||||||
|
final a = b1 * c2 - b2 * c1;
|
||||||
|
final b = a2 * c1 - a1 * c2;
|
||||||
|
final c = a1 * b2 - b1 * a2;
|
||||||
|
final d = -(a * x1 + b * y1 + c * z1);
|
||||||
|
|
||||||
|
return Vector3(a, b, c);
|
||||||
|
|
||||||
|
print('a: $a, b: $b, c: $c, d: $d');
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user