我正在尝试使用rect值从原始捕获的图像中裁剪出面部,以识别目标区域并创建仅面部检测区域的位图。这有效:)
问题是:
当我的图像具有一个以上的面孔时,onSuccess方法中的for循环会在警报对话框onClick()完成之前循环调用,该警报对话框用于为每个裁剪的面部文件名输入用户输入。调用警报对话框的onClick(OK)方法后,将触发用于保存每个面孔的代码。
该代码当前仅保存一个裁剪的面孔,在单独的警报对话框中可以正确处理不同的用户输入,但仅保存的最后一个面孔。
我认为,在触发警报对话框之后,但在用户完成输入并为每个面孔进行保存之前,for循环仍在继续循环。因此,当调用save方法时,它只会保存面孔列表中的最后一个对象。
关于如何改进此代码的任何建议?
@Override
public void onImage(CameraKitImage cameraKitImage) {
capturedImage = cameraKitImage.getBitmap();
capturedImage = Bitmap.createScaledBitmap(capturedImage, cameraView.getWidth(), cameraView.getHeight(), false);
cameraView.stop();
processFaceDetection(capturedImage);
}
public void processFaceDetection(final Bitmap bitmap) {
FirebaseVisionImage visionImage = FirebaseVisionImage.fromBitmap(bitmap);
FirebaseVisionFaceDetectorOptions detectorOptions = new FirebaseVisionFaceDetectorOptions.Builder()
.setPerformanceMode(FirebaseVisionFaceDetectorOptions.ACCURATE)
.setLandmarkMode(FirebaseVisionFaceDetectorOptions.NO_LANDMARKS)
.setClassificationMode(FirebaseVisionFaceDetectorOptions.NO_CLASSIFICATIONS)
.setMinFaceSize(0.15f)
.enableTracking()
.build();
FirebaseVisionFaceDetector detector = FirebaseVision.getInstance().getVisionFaceDetector(detectorOptions);
detector.detectInImage(visionImage).addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionFace>>() {
@Override
public void onSuccess(List<FirebaseVisionFace> firebaseVisionFaces) {
listSize = firebaseVisionFaces.size();
Bitmap originalCapture = Bitmap.createScaledBitmap(capturedImage, cameraView.getWidth(), cameraView.getHeight(), false);//scaled bitmap created from captured image
saveImageOriginal(originalCapture);
//for (FirebaseVisionFace face : firebaseVisionFaces) {
for ( i = 0; i < firebaseVisionFaces.size(); i++){
FirebaseVisionFace face = firebaseVisionFaces.get(i);
Rect rect = face.getBoundingBox();
faceCrop = Bitmap.createBitmap(originalCapture, rect.left, rect.top, rect.width(), rect.height());//face cropped using rect values
RectOverlay rectOverlay = new RectOverlay(graphicOverlay, rect);
graphicOverlay.add(rectOverlay);//draw box around face
showAddItemDialog(Camera.CurrentContext); //prompt for name, save cropped face
}
}
});
}
private void showAddItemDialog(Context c) {
final EditText inputName = new EditText(c);
AlertDialog dialog = new AlertDialog.Builder(c)
.setTitle("Input Person's Name" + i)
.setMessage("Format: LastName, FirstName")
.setView(inputName)
.setPositiveButton("Add", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
nameIn = String.valueOf(inputName.getText());
try {
saveImage(faceCrop); //give read write permission
}catch (Exception e) {
e.printStackTrace();
}
}
})
.setNegativeButton("Cancel", null)
.create();
dialog.show();
}
public String saveImage(Bitmap croppedFace) {
String eventFaces, event;
event = "/Summer Event 2020";
eventFaces = "/Event_Faces";
final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
croppedFace.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
final File facesDirectory = new File(getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + event + eventFaces); //crop
if (!facesDirectory.exists()) {
Log.d("directory SAVING", "" + facesDirectory.mkdirs());
facesDirectory.mkdirs();
}
try {
croppedFile = new File(facesDirectory, nameIn + ".jpg");
croppedFile.createNewFile();
FileOutputStream fo = new FileOutputStream(croppedFile);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(Camera.CurrentContext, new String[]{croppedFile.getPath()}, new String[]{"image/jpeg"}, null);
fo.close();
Log.d("TAG", "File Saved::--->" + croppedFile.getAbsolutePath());
Toast.makeText(Camera.this, nameIn + " " + "i" + i + " list" + listSize + " " + "Face Cropped and Saved to -> " + croppedFile.getPath(), Toast.LENGTH_SHORT).show();
return croppedFile.getAbsolutePath();
} catch (IOException e1) {
e1.printStackTrace();
}
return "";
}//end of save image
答案 0 :(得分:0)
如果有人遇到相同类型的问题,我将for循环中的代码分为两个单独的循环,并在用户输入(键盘输入)中将一个标志合并到AlertDialog中。一旦该标志为true,则在AlertDialog用户输入之后,现在将满足第二个for循环的条件。
希望这会有所帮助。