Ответ 1
NEW: Я управляю всеми моими поворотами телефона. Значение offsetDxDy зависит от моего макета, но если я должен сказать вам правду, я не знаю, почему я ставлю значение 100. Это хорошо работает на моем Huawei P9, и я нашел его эмпирическим способом. Я все еще не пытался выяснить, зависит ли это от моего телефона или от моего XML-макета или того и другого.
В любом случае матрицы теперь найдены, поэтому вы можете адаптировать их так, чтобы они соответствовали вашим потребностям.
Примечание: my setRotation
не является настолько общим, потому что я не параметризировал его на
int orientationOffset = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
Вы можете попробовать сделать это, чтобы иметь полный общий код, работающий с SENSOR_ORIENTATION
, отличный от того, который указан в этом примере, который равен 270.
Таким образом, этот код работает с телефоном с аппаратным датчиком камеры с ориентацией 270.
У Huawei P9 есть.
Просто, чтобы дать вам представление о привязке вращения к ориентации датчика HW, которая также хорошо работает на моем P9 (но у меня нет другого оборудования для тестирования)
if (mSwappedDimensions) {
// Display Rotation 0
mFaceDetectionMatrix.setRotate(orientationOffset);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(mPreviewSize.getHeight() + offsetDxDy, mPreviewSize.getWidth() + offsetDxDy);
} else {
// Display Rotation 90 e 270
if (displayRotation == Surface.ROTATION_90) {
mFaceDetectionMatrix.setRotate(orientationOffset + 90);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(mPreviewSize.getWidth() + offsetDxDy, -offsetDxDy);
} else if (displayRotation == Surface.ROTATION_270) {
mFaceDetectionMatrix.setRotate(orientationOffset + 270);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(-offsetDxDy, mPreviewSize.getHeight() + offsetDxDy);
}
}
Здесь мой последний код (также доступен на GitHub)
int orientationOffset = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
Rect activeArraySizeRect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
// Face Detection Matrix
mFaceDetectionMatrix = new Matrix();
Log.i("Test", "activeArraySizeRect1: (" + activeArraySizeRect + ") -> " + activeArraySizeRect.width() + ", " + activeArraySizeRect.height());
Log.i("Test", "activeArraySizeRect2: " + mPreviewSize.getWidth() + ", " + mPreviewSize.getHeight());
float s1 = mPreviewSize.getWidth() / (float)activeArraySizeRect.width();
float s2 = mPreviewSize.getHeight() / (float)activeArraySizeRect.height();
//float s1 = mOverlayView.getWidth();
//float s2 = mOverlayView.getHeight();
boolean mirror = (facing == CameraCharacteristics.LENS_FACING_FRONT); // we always use front face camera
boolean weAreinPortrait = true;
int offsetDxDy = 100;
if (mSwappedDimensions) {
// Display Rotation 0
mFaceDetectionMatrix.setRotate(270);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(mPreviewSize.getHeight() + offsetDxDy, mPreviewSize.getWidth() + offsetDxDy);
} else {
// Display Rotation 90 e 270
if (displayRotation == Surface.ROTATION_90) {
mFaceDetectionMatrix.setRotate(0);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(mPreviewSize.getWidth() + offsetDxDy, -offsetDxDy);
} else if (displayRotation == Surface.ROTATION_270) {
mFaceDetectionMatrix.setRotate(180);
mFaceDetectionMatrix.postScale(mirror ? -s1 : s1, s2);
mFaceDetectionMatrix.postTranslate(-offsetDxDy, mPreviewSize.getHeight() + offsetDxDy);
}
}
Это публичное рефери github, где вы можно найти код: https://github.com/shadowsheep1/android-camera2-api-face-recon. Надеюсь, помочь тебе.
В любом случае, чтобы дать вам также некоторую теорию, то, что вы делаете, - это двумерное преобразование плоскости. Я имею в виду, что у вас есть плоскость (HW Sensor), и вам нужно переназначить объект на этом самолете на плоскости предварительного просмотра.
Итак, вам нужно позаботиться о:
- Вращение. Это зависит от вашего вращения датчика HW и вращения телефона.
- Зеркалирование. Горизонтальное зеркалирование, которое зависит, если вы используете камеру на передней панели или нет, и вертикальное зеркалирование, зависящее от вращения телефона). Зеркалирование выполняется с помощью знака "-" в матрице масштабирования.
- Перевод. Это зависит от того, где ваш объект был помещен вращением (которое также зависит от того, из какого центра вращения вы имеете дело) и перевода. Таким образом, вы должны заменить в своем предварительном просмотре. Просмотрите свои объекты.
Математическая теория
Я также написал технический пост в своем блоге некоторое время назад, но они на итальянском языке.