- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用视觉 API 来跟踪人脸。我根据面部位置应用了一个蒙版。当我从前置摄像头拍照时,我调用 camerasource.takePicture() 来保存图像。我在某些设备(如三星)中面临图像旋转问题,捕获图像显示蒙版和面部不同的不同位置。我使用 Exif 类来获取图像的方向,但它总是返回 0,所以我无法旋转图像。我正在使用以下类(class)来获取方向和旋转图像。
public class ExifUtils {
public Bitmap rotateBitmap(String src, Bitmap bitmap) {
try {
int orientation = getExifOrientation(src);
if (orientation == 1) {
return bitmap;
}
Matrix matrix = new Matrix();
switch (orientation) {
case 2:
matrix.setScale(-1, 1);
break;
case 3:
matrix.setRotate(180);
break;
case 4:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case 5:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case 6:
matrix.setRotate(90);
break;
case 7:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case 8:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try {
Bitmap oriented = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return oriented;
} catch (OutOfMemoryError e) {
e.printStackTrace();
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
private int getExifOrientation(String src) throws IOException {
int orientation = 1;
try {
if (Build.VERSION.SDK_INT >= 5) {
Class<?> exifClass = Class
.forName("android.media.ExifInterface");
Constructor<?> exifConstructor = exifClass
.getConstructor(new Class[]{String.class});
Object exifInstance = exifConstructor
.newInstance(new Object[]{src});
Method getAttributeInt = exifClass.getMethod("getAttributeInt",
new Class[]{String.class, int.class});
Field tagOrientationField = exifClass
.getField("TAG_ORIENTATION");
String tagOrientation = (String) tagOrientationField.get(null);
orientation = (Integer) getAttributeInt.invoke(exifInstance,
new Object[]{tagOrientation, 1});
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Fragment.InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (java.lang.InstantiationException e) {
e.printStackTrace();
}
return orientation;
}
我找到了这个 issue在vision api中有没有什么解决办法。
最佳答案
我自己解决我的问题。我从字节数据中获取方向,然后根据方向旋转我的图像。
private CameraSource.PictureCallback mPicture = new CameraSource.PictureCallback() {
@Override
public void onPictureTaken(byte[] bytes) {
int orientation = Exif.getOrientation(bytes);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
switch(orientation) {
case 90:
bitmapPicture= rotateImage(bitmap, 90);
break;
case 180:
bitmapPicture= rotateImage(bitmap, 180);
break;
case 270:
bitmapPicture= rotateImage(bitmap, 270);
break;
case 0:
// if orientation is zero we don't need to rotate this
default:
break;
}
//write your code here to save bitmap
}
}
};
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
true);
}
下面的类用于从 byte[] 数据中获取方向。
public class Exif {
private static final String TAG = "CameraExif";
// Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
public static int getOrientation(byte[] jpeg) {
if (jpeg == null) {
return 0;
}
int offset = 0;
int length = 0;
// ISO/IEC 10918-1:1993(E)
while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) {
int marker = jpeg[offset] & 0xFF;
// Check if the marker is a padding.
if (marker == 0xFF) {
continue;
}
offset++;
// Check if the marker is SOI or TEM.
if (marker == 0xD8 || marker == 0x01) {
continue;
}
// Check if the marker is EOI or SOS.
if (marker == 0xD9 || marker == 0xDA) {
break;
}
// Get the length and check if it is reasonable.
length = pack(jpeg, offset, 2, false);
if (length < 2 || offset + length > jpeg.length) {
Log.e(TAG, "Invalid length");
return 0;
}
// Break if the marker is EXIF in APP1.
if (marker == 0xE1 && length >= 8 &&
pack(jpeg, offset + 2, 4, false) == 0x45786966 &&
pack(jpeg, offset + 6, 2, false) == 0) {
offset += 8;
length -= 8;
break;
}
// Skip other markers.
offset += length;
length = 0;
}
// JEITA CP-3451 Exif Version 2.2
if (length > 8) {
// Identify the byte order.
int tag = pack(jpeg, offset, 4, false);
if (tag != 0x49492A00 && tag != 0x4D4D002A) {
Log.e(TAG, "Invalid byte order");
return 0;
}
boolean littleEndian = (tag == 0x49492A00);
// Get the offset and check if it is reasonable.
int count = pack(jpeg, offset + 4, 4, littleEndian) + 2;
if (count < 10 || count > length) {
Log.e(TAG, "Invalid offset");
return 0;
}
offset += count;
length -= count;
// Get the count and go through all the elements.
count = pack(jpeg, offset - 2, 2, littleEndian);
while (count-- > 0 && length >= 12) {
// Get the tag and check if it is orientation.
tag = pack(jpeg, offset, 2, littleEndian);
if (tag == 0x0112) {
// We do not really care about type and count, do we?
int orientation = pack(jpeg, offset + 8, 2, littleEndian);
switch (orientation) {
case 1:
return 0;
case 3:
return 180;
case 6:
return 90;
case 8:
return 270;
}
Log.i(TAG, "Unsupported orientation");
return 0;
}
offset += 12;
length -= 12;
}
}
Log.i(TAG, "Orientation not found");
return 0;
}
private static int pack(byte[] bytes, int offset, int length,
boolean littleEndian) {
int step = 1;
if (littleEndian) {
offset += length - 1;
step = -1;
}
int value = 0;
while (length-- > 0) {
value = (value << 8) | (bytes[offset] & 0xFF);
offset += step;
}
return value;
}
}
关于android - camerasource.takePicture() 在某些设备中保存旋转的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39443657/
我有两个安卓设备。 CameraSource 对他们的工作方式不同。对于一台设备,照片的方向在保存后没有旋转是正确的。但是对于另一台设备,保存的照片方向错误。 我已经创建了 CameraSource:
当我想使用相机拍照时,CameraSource 出现了一些问题。我想要的只是用我在 xml 文件上制作的按钮拍照并使用“CameraSource”拍照,因为我也在使用“TextRecognizer”。
我正在实现 google-vision face tracker 中给出的示例.MyFaceDetector 类: public class MyFaceDetector extends Detect
我正在使用视觉 API 来跟踪人脸。我根据面部位置应用了一个蒙版。当我从前置摄像头拍照时,我调用 camerasource.takePicture() 来保存图像。我在某些设备(如三星)中面临图像旋转
我一直在关注以下tutorial ,它使用移动视觉 api 创建条形码/二维码扫描仪。虽然我已经输入了它所说的确切代码(至少我认为),但来自 cameraSource 的摄像头馈送。 我在这个过程中添
我正在使用 google vision api 构建一个具有二维码扫描仪的应用程序。读取二维码后我无法停止相机。流程是 MainActivity -> QrActivity一旦二维码收到检测,应用程序
我使用 Vision API 扫描条码。几乎完成了,除了自动对焦。我遵循此链接中的指南:https://developers.google.com/android/reference/com/goog
背景:我正在实现一个 mask 来帮助人们聚焦他们的相机并在每张照片上产生统一的结果。可悲的是, mask 需要在前后摄像头之间切换时调整其大小,以便为人们提供很好的指导。 问题:我一直在尝试检测相机
我正在开发一个 android 应用程序,它允许用户检查 QR 码内容并根据读取结果执行某些操作。 为了提高性能,我想实现两种方法: onClickFocus(允许用户在点击屏幕时对焦相机) 打开/关
我有一个初始化条形码检测的 Activity 。然后我转到另一个 Activity ,当我按下后退按钮时,它会触发此异常的循环: com.example.myapp E/CameraSource: E
我正在尝试开发一个带有人脸检测功能的简单相机应用程序,我正在使用这里的 android-vision 示例 https://github.com/googlesamples/android-visio
现在,我们的应用程序正在成功运行 Snapdragon SDK。我们正在尝试在我们的项目中实现 Vision 8.3.0 中的 FaceDetector,以增加兼容设备的数量。我们不能使用 Camer
我已从此处查看最新的 Google Vision API: https://github.com/googlesamples/android-vision 我在带有 KitKat 的 LG G2 设备
基于 Google Vision Face Tracker 的面部追踪器应用程序.默认情况下,Face Tracker 使用后置/后置摄像头,但我想使用前置摄像头检测人脸。 这是google visi
移动视觉API中的setRequestedFps是什么意思。 相机代码: mCameraSource = new CameraSource.Builder(getApplica
这个问题是关于使用 Google's Mobile Vision Face API在 Android 上。 故事(背景)和我想做的事 我正在尝试实现一个功能,该功能可以检测相机 View 中的人脸,并
我必须在 Google Vision API 的 CameraSource 中实现来构建相机并在捕获图像之前进行面部检测。现在我遇到了一些问题,所以我需要从 CameraSource 访问相机对象。
我正在尝试抓取相机捕获的帧,对它们进行编码,最后使用 RTP/RTSP 发送它们。 为了进行捕捉,我使用了 stagefright 的 CameraSource 类。屏幕上的预览(从 Java 传递的
下面是我的条形码扫描器 Activity ,除了 setAutoFocusEnabled(true) 之外一切正常。它在运行时返回一条消息,指出我的设备不支持自动对焦,尽管 Samsung Tab E
我是一名优秀的程序员,十分优秀!