如何防止 For 循环继续循环,直到循环内调用的方法完成?
How do I prevent a For loop from continuing to loop, until a method called within the loop, is complete?
我正在尝试使用矩形值从原始捕获的图像中裁剪面部,以识别目标区域并创建仅面部检测区域的位图。这有效:)
问题是:
当我有一个包含多个面孔的图像时,onSuccess 方法中的 for 循环似乎在警报对话框 onClick() 完成之前循环,该方法为每个裁剪的面孔文件名调用用户输入的警报对话框。一旦调用警报对话框的 onClick (OK) 方法,就会触发保存每张面孔的代码。
代码目前只保存裁剪后的一张脸,不同的用户输入在各个警告对话框中得到正确处理,但只保存最后一张脸。
我认为,for 循环在触发警报对话框之后但在用户完成输入并为每张脸保存之前继续循环。因此,当调用保存方法时,它只保存面列表中的最后一个对象。
关于如何改进此代码的任何建议?
@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
如果有人遇到同样类型的问题,我将 for 循环中的代码分成两个单独的循环,并在用户输入(键盘输入)时将标志合并到 AlertDialog 中。一旦标志为真,在 AlertDialog 用户输入之后,现在将满足第二个 for 循环的条件。
希望对您有所帮助。
我正在尝试使用矩形值从原始捕获的图像中裁剪面部,以识别目标区域并创建仅面部检测区域的位图。这有效:)
问题是:
当我有一个包含多个面孔的图像时,onSuccess 方法中的 for 循环似乎在警报对话框 onClick() 完成之前循环,该方法为每个裁剪的面孔文件名调用用户输入的警报对话框。一旦调用警报对话框的 onClick (OK) 方法,就会触发保存每张面孔的代码。
代码目前只保存裁剪后的一张脸,不同的用户输入在各个警告对话框中得到正确处理,但只保存最后一张脸。
我认为,for 循环在触发警报对话框之后但在用户完成输入并为每张脸保存之前继续循环。因此,当调用保存方法时,它只保存面列表中的最后一个对象。
关于如何改进此代码的任何建议?
@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
如果有人遇到同样类型的问题,我将 for 循环中的代码分成两个单独的循环,并在用户输入(键盘输入)时将标志合并到 AlertDialog 中。一旦标志为真,在 AlertDialog 用户输入之后,现在将满足第二个 for 循环的条件。
希望对您有所帮助。