人脸检测API-坐标
Face Detection API- coordinates
所以我正在使用 API 来检测图像中的人脸,到目前为止它对我来说效果很好。然而,我一直无法弄清楚如何将图像裁剪到脸上。我知道如何裁剪位图,但它需要获取位图中脸部的左上角位置以及宽度和高度。当我使用
查询左上角位置时
points = face.getPosition();
Bitmap bmp = Bitmap.createBitmap(bit,(int)points.x,(int)(-1.0*points.y),(int)face.getWidth(),(int)face.getHeight());
但是当我查看点时,我注意到 y 是 -63.5555,x 是 235.6666;我不明白为什么会有负 y 坐标。我做了一些调试并查看了面部对象的内部;我发现它包含一个已经具有正 x 和 y 坐标的 PointF 对象。那么为什么在这种情况下返回负 y 坐标?
我以前用过同样的API,并且能够成功裁剪脸部。
尝试
//Crop face option
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);
Bitmap bitmap = getRotatedImageToUpload(pictureFile.getAbsolutePath());
Bitmap faceBitmap = Bitmap.createBitmap(bitmap, (int) faceCentre.x, (int) faceCentre.y, (int) faceWidth, (int) faceHeight);
FileOutputStream out = null;
try {
out = new FileOutputStream(getOutputMediaFile());
faceBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//End of Crop face option
getRotateImageToUpload 的代码是
public Bitmap getRotatedImageToUpload(String filePath) {
try {
String file = filePath;
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);
BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);
ExifInterface exif = null;
exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);
return rotatedBitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
边界框估计头部的尺寸,即使它在照片中可能不完全可见。如果面部被图像的顶部或左侧裁剪,则坐标可能为负(例如,头顶被裁剪掉图片的顶部,导致 y 坐标大于 0)。
您在调试中看到的差异是由于实现在内部使用头部中心位置来表示位置(大约在眼睛之间的中点),但是 API 翻译为方便起见,在您调用 getPosition 时将其置于左上角。
另请注意,边界框不一定是脸部的紧密边界。如果您想要更紧密的配合,您应该启用地标检测并计算相对于返回的地标的所需裁剪级别。
所以我正在使用 API 来检测图像中的人脸,到目前为止它对我来说效果很好。然而,我一直无法弄清楚如何将图像裁剪到脸上。我知道如何裁剪位图,但它需要获取位图中脸部的左上角位置以及宽度和高度。当我使用
查询左上角位置时 points = face.getPosition();
Bitmap bmp = Bitmap.createBitmap(bit,(int)points.x,(int)(-1.0*points.y),(int)face.getWidth(),(int)face.getHeight());
但是当我查看点时,我注意到 y 是 -63.5555,x 是 235.6666;我不明白为什么会有负 y 坐标。我做了一些调试并查看了面部对象的内部;我发现它包含一个已经具有正 x 和 y 坐标的 PointF 对象。那么为什么在这种情况下返回负 y 坐标?
我以前用过同样的API,并且能够成功裁剪脸部。
尝试
//Crop face option
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);
Bitmap bitmap = getRotatedImageToUpload(pictureFile.getAbsolutePath());
Bitmap faceBitmap = Bitmap.createBitmap(bitmap, (int) faceCentre.x, (int) faceCentre.y, (int) faceWidth, (int) faceHeight);
FileOutputStream out = null;
try {
out = new FileOutputStream(getOutputMediaFile());
faceBitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//End of Crop face option
getRotateImageToUpload 的代码是
public Bitmap getRotatedImageToUpload(String filePath) {
try {
String file = filePath;
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);
BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);
ExifInterface exif = null;
exif = new ExifInterface(file);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);
return rotatedBitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
边界框估计头部的尺寸,即使它在照片中可能不完全可见。如果面部被图像的顶部或左侧裁剪,则坐标可能为负(例如,头顶被裁剪掉图片的顶部,导致 y 坐标大于 0)。
您在调试中看到的差异是由于实现在内部使用头部中心位置来表示位置(大约在眼睛之间的中点),但是 API 翻译为方便起见,在您调用 getPosition 时将其置于左上角。
另请注意,边界框不一定是脸部的紧密边界。如果您想要更紧密的配合,您应该启用地标检测并计算相对于返回的地标的所需裁剪级别。