When utilizing CameraX with TensorFlow for object detection, I encountered an issue related to the positioning of rectangular detection boxes within the camera preview. Specifically, the overlay functionality functions correctly, accurately delineating objects within the specified rectangular region, when the preview resolution is set to `setTargetAspectRatio(AspectRatio.RATIO_16_9)`.
However, in order to obtain cropped images of the detected objects at higher resolutions, I utilize the `.setResolutionSelector()` method with a `ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY` parameter. This ensures that the preview resolution is set to the highest available option, which is essential for obtaining clear images of the detected objects. Maintaining a default resolution results in low-quality images, which, when cropped, further deteriorate in clarity.
Upon implementing the high-resolution settings within both the `ImageAnalyzer` and the Camera Preview, I encountered an unexpected behavior where the bounding boxes are drawn on the preview no longer aligned with the actual objects. This misalignment adversely affects the subsequent cropping process, leading to inaccuracies in the resultant images. Conversely, when utilizing the `AspectRatio.RATIO_16_9`, the bounding boxes are correctly positioned, and the cropping process functions as expected.
It is imperative to resolve this discrepancy to ensure accurate object detection and cropping at higher resolutions, in line with project requirements.
Below mentioned code is working when ImageAnalyzer and CameraPreview target resolution is set to
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
This is my cropping method of rectangular box which is not working according to the expectation
public Bitmap croppedBitmap(Bitmap rotated) {
//calculate aspect ratio
float koefX = (float) rotated.getWidth() / (float) previewView.getWidth();
float koefY = (float) rotated.getHeight() / (float) previewView.getHeight();
//get viewfinder border size and position on the screen
int x1 = borderCamera.getLeft();
int y1 = borderCamera.getTop();
int x2 = borderCamera.getWidth();
int y2 = borderCamera.getHeight();
//calculate position and size for cropping
int cropStartX = Math.round(x1 * koefX);
int cropStartY = Math.round(y1 * koefY);
int cropWidthX = Math.round(x2 * koefX);
int cropHeightY = Math.round(y2 * koefY);
//check limits and make crop
if (cropStartX + cropWidthX <= rotated.getWidth() && cropStartY + cropHeightY <= rotated.getHeight()) {
/*
This is the cropped bitmap image we will pass it into create image file function
* */
croppedBitmap = Bitmap.createBitmap(rotated, cropStartX, cropStartY , cropWidthX, cropHeightY );
} else {
croppedBitmap = null;
}
return croppedBitmap;
}
This is the bounding boxes code
private var scaleFactor: Float = 1f
val boundingBox = result.boundingBox
val top = boundingBox.top * scaleFactor
val bottom = boundingBox.bottom * scaleFactor
val left = boundingBox.left * scaleFactor
val right = boundingBox.right * scaleFactor
// Draw bounding box around detected objects
val drawableRect = RectF(left, top, right, bottom)
canvas.drawRect(drawableRect, boxPaint)