capacitor-plugin-camera-forked 3.1.121 → 3.1.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -56,7 +56,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|
|
56
56
|
public class BlurDetectionHelper {
|
|
57
57
|
private static final String TAG = "BlurDetectionHelper";
|
|
58
58
|
private static final String MODEL_FILENAME = "blur_detection_model.tflite";
|
|
59
|
-
private static int INPUT_SIZE =
|
|
59
|
+
private static int INPUT_SIZE = 600; // Will be updated based on actual model input size
|
|
60
60
|
private static final int NUM_CLASSES = 2; // blur, sharp
|
|
61
61
|
|
|
62
62
|
// Timeout settings
|
|
@@ -66,6 +66,11 @@ public class BlurDetectionHelper {
|
|
|
66
66
|
private static final double MIN_WORD_CONFIDENCE = 0.8; // 80% confidence threshold
|
|
67
67
|
private static final double AT_LEAST_N_PERCENT_OF_WORDS_ARE_READABLE = 0.6; // 60% of words are readable
|
|
68
68
|
private static final double AT_LEAST_N_PERCENT_OF_AVERAGE_CONFIDENCE = 0.85; // 85% of average confidence
|
|
69
|
+
|
|
70
|
+
// Method based confidence threshold
|
|
71
|
+
private static final double MIN_SHARP_CONFIDENCE_FOR_OBJECT_DETECTION = 0.75; // 75% confidence threshold
|
|
72
|
+
private static final double MIN_SHARP_CONFIDENCE_FOR_TEXT_DETECTION = 0.15; // 15% confidence threshold
|
|
73
|
+
private static final double MIN_SHARP_CONFIDENCE_FOR_FULL_IMAGE = 0.75; // 70% confidence threshold
|
|
69
74
|
|
|
70
75
|
// TFLite components
|
|
71
76
|
private Interpreter tflite;
|
|
@@ -91,10 +96,9 @@ public class BlurDetectionHelper {
|
|
|
91
96
|
|
|
92
97
|
|
|
93
98
|
public BlurDetectionHelper() {
|
|
94
|
-
// Initialize image processor for MobileNetV2 preprocessing
|
|
99
|
+
// Initialize image processor for MobileNetV2 preprocessing with aspect ratio preservation
|
|
95
100
|
imageProcessor = new ImageProcessor.Builder()
|
|
96
|
-
.add(new ResizeWithCropOrPadOp(INPUT_SIZE, INPUT_SIZE))
|
|
97
|
-
.add(new ResizeOp(INPUT_SIZE, INPUT_SIZE, ResizeOp.ResizeMethod.BILINEAR))
|
|
101
|
+
.add(new ResizeWithCropOrPadOp(INPUT_SIZE, INPUT_SIZE)) // This preserves aspect ratio by cropping/padding
|
|
98
102
|
.build();
|
|
99
103
|
|
|
100
104
|
// Initialize common words dictionary
|
|
@@ -146,10 +150,9 @@ public class BlurDetectionHelper {
|
|
|
146
150
|
if (modelInputSize != INPUT_SIZE) {
|
|
147
151
|
INPUT_SIZE = modelInputSize;
|
|
148
152
|
|
|
149
|
-
// Recreate image processor with correct size
|
|
153
|
+
// Recreate image processor with correct size and aspect ratio preservation
|
|
150
154
|
imageProcessor = new ImageProcessor.Builder()
|
|
151
|
-
.add(new ResizeWithCropOrPadOp(INPUT_SIZE, INPUT_SIZE))
|
|
152
|
-
.add(new ResizeOp(INPUT_SIZE, INPUT_SIZE, ResizeOp.ResizeMethod.BILINEAR))
|
|
155
|
+
.add(new ResizeWithCropOrPadOp(INPUT_SIZE, INPUT_SIZE)) // Preserves aspect ratio
|
|
153
156
|
.build();
|
|
154
157
|
}
|
|
155
158
|
}
|
|
@@ -239,7 +242,7 @@ public class BlurDetectionHelper {
|
|
|
239
242
|
Bitmap roi = cropBitmap(bitmap, boundingBox);
|
|
240
243
|
if (roi != null) {
|
|
241
244
|
// Run TFLite blur detection on ROI
|
|
242
|
-
Map<String, Object> roiResult = detectBlurWithTFLiteConfidence(roi);
|
|
245
|
+
Map<String, Object> roiResult = detectBlurWithTFLiteConfidence(roi, MIN_SHARP_CONFIDENCE_FOR_OBJECT_DETECTION);
|
|
243
246
|
|
|
244
247
|
Log.d(TAG, "Object Detection ROI Result isBlur: " + roiResult.get("isBlur"));
|
|
245
248
|
roiResult.put("boundingBox", boundingBox);
|
|
@@ -299,7 +302,7 @@ public class BlurDetectionHelper {
|
|
|
299
302
|
|
|
300
303
|
// Step 3: Full-Image Blur Detection (Final Fallback)
|
|
301
304
|
Log.d(TAG, "Step 3: Using Full-Image Blur Detection");
|
|
302
|
-
return detectBlurWithTFLiteConfidence(bitmap);
|
|
305
|
+
return detectBlurWithTFLiteConfidence(bitmap, MIN_SHARP_CONFIDENCE_FOR_FULL_IMAGE);
|
|
303
306
|
|
|
304
307
|
} catch (Exception e) {
|
|
305
308
|
Log.e(TAG, "Error in blur detection pipeline: " + e.getMessage());
|
|
@@ -329,6 +332,9 @@ public class BlurDetectionHelper {
|
|
|
329
332
|
// Preprocess image for model (resize and potential enhancement)
|
|
330
333
|
inputImageBuffer.load(processedBitmap);
|
|
331
334
|
inputImageBuffer = imageProcessor.process(inputImageBuffer);
|
|
335
|
+
|
|
336
|
+
// Ensure black padding for better accuracy (matches iOS implementation)
|
|
337
|
+
ensureBlackPadding(inputImageBuffer);
|
|
332
338
|
|
|
333
339
|
// Get tensor buffer
|
|
334
340
|
ByteBuffer tensorBuffer = inputImageBuffer.getBuffer();
|
|
@@ -355,7 +361,7 @@ public class BlurDetectionHelper {
|
|
|
355
361
|
double sharpConfidence = probabilities.length > 1 ? probabilities[1] : 0.0;
|
|
356
362
|
|
|
357
363
|
// Determine if image is blurry using TFLite confidence
|
|
358
|
-
boolean isBlur = sharpConfidence <
|
|
364
|
+
boolean isBlur = sharpConfidence < MIN_SHARP_CONFIDENCE_FOR_FULL_IMAGE;
|
|
359
365
|
|
|
360
366
|
|
|
361
367
|
// Return 1.0 for blur, 0.0 for sharp (to maintain double return type)
|
|
@@ -420,6 +426,37 @@ public class BlurDetectionHelper {
|
|
|
420
426
|
return normalizedBuffer;
|
|
421
427
|
}
|
|
422
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Ensure black padding in the processed image buffer for better accuracy
|
|
431
|
+
* @param tensorImage Processed tensor image
|
|
432
|
+
*/
|
|
433
|
+
private void ensureBlackPadding(TensorImage tensorImage) {
|
|
434
|
+
ByteBuffer buffer = tensorImage.getBuffer();
|
|
435
|
+
DataType dataType = tensorImage.getDataType();
|
|
436
|
+
|
|
437
|
+
if (dataType == DataType.FLOAT32) {
|
|
438
|
+
// For float32, ensure padding areas are 0.0 (black)
|
|
439
|
+
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
|
440
|
+
int totalPixels = INPUT_SIZE * INPUT_SIZE * 3;
|
|
441
|
+
|
|
442
|
+
// Check if we need to fill with zeros (black)
|
|
443
|
+
for (int i = 0; i < totalPixels; i++) {
|
|
444
|
+
if (floatBuffer.get(i) < 0.001f) { // Near zero values
|
|
445
|
+
floatBuffer.put(i, 0.0f); // Ensure exact zero (black)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
} else if (dataType == DataType.UINT8) {
|
|
449
|
+
// For uint8, ensure padding areas are 0 (black)
|
|
450
|
+
buffer.rewind();
|
|
451
|
+
while (buffer.hasRemaining()) {
|
|
452
|
+
byte value = buffer.get();
|
|
453
|
+
if (value == 0) {
|
|
454
|
+
buffer.put(buffer.position() - 1, (byte) 0); // Ensure exact zero
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
423
460
|
/**
|
|
424
461
|
* Normalize image buffer from uint8 [0,255] to float32 [0,1]
|
|
425
462
|
* @param uint8Buffer Input buffer with uint8 pixel values
|
|
@@ -498,7 +535,7 @@ public class BlurDetectionHelper {
|
|
|
498
535
|
* @param bitmap Input image bitmap
|
|
499
536
|
* @return Map with isBlur, blurConfidence, and sharpConfidence
|
|
500
537
|
*/
|
|
501
|
-
public java.util.Map<String, Object> detectBlurWithTFLiteConfidence(Bitmap bitmap) {
|
|
538
|
+
public java.util.Map<String, Object> detectBlurWithTFLiteConfidence(Bitmap bitmap, double minSharpConfidence) {
|
|
502
539
|
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
|
503
540
|
|
|
504
541
|
if (!isInitialized || tflite == null) {
|
|
@@ -525,6 +562,9 @@ public class BlurDetectionHelper {
|
|
|
525
562
|
// Preprocess image for model (resize and potential enhancement)
|
|
526
563
|
inputImageBuffer.load(processedBitmap);
|
|
527
564
|
inputImageBuffer = imageProcessor.process(inputImageBuffer);
|
|
565
|
+
|
|
566
|
+
// Ensure black padding for better accuracy (matches iOS implementation)
|
|
567
|
+
ensureBlackPadding(inputImageBuffer);
|
|
528
568
|
|
|
529
569
|
// Get tensor buffer
|
|
530
570
|
ByteBuffer tensorBuffer = inputImageBuffer.getBuffer();
|
|
@@ -553,7 +593,7 @@ public class BlurDetectionHelper {
|
|
|
553
593
|
Log.d(TAG, "TFLite Blur confidence: " + blurConfidence + " Sharp confidence: " + sharpConfidence);
|
|
554
594
|
|
|
555
595
|
// Determine if image is blurry using TFLite confidence
|
|
556
|
-
boolean isBlur = sharpConfidence <
|
|
596
|
+
boolean isBlur = sharpConfidence < minSharpConfidence;
|
|
557
597
|
|
|
558
598
|
Log.d(TAG, "TFLite Blur detection isBlur: " + isBlur);
|
|
559
599
|
|
|
@@ -783,7 +823,7 @@ public class BlurDetectionHelper {
|
|
|
783
823
|
try {
|
|
784
824
|
Bitmap cropped = cropBitmap(bitmap, roi);
|
|
785
825
|
if (cropped != null) {
|
|
786
|
-
Map<String, Object> result = detectBlurWithTFLiteConfidence(cropped);
|
|
826
|
+
Map<String, Object> result = detectBlurWithTFLiteConfidence(cropped, MIN_SHARP_CONFIDENCE_FOR_TEXT_DETECTION);
|
|
787
827
|
result.put("boundingBox", roi);
|
|
788
828
|
results.add(result);
|
|
789
829
|
}
|
|
@@ -12,8 +12,8 @@ import MLKitVision
|
|
|
12
12
|
class BlurDetectionHelper {
|
|
13
13
|
|
|
14
14
|
private static let TAG = "BlurDetectionHelper"
|
|
15
|
-
private static let INPUT_WIDTH =
|
|
16
|
-
private static let INPUT_HEIGHT =
|
|
15
|
+
private static let INPUT_WIDTH = 600 // Model's expected input width
|
|
16
|
+
private static let INPUT_HEIGHT = 600 // Model's expected input height
|
|
17
17
|
private static let BATCH_SIZE = 1 // Model expects a batch size of 1
|
|
18
18
|
private static let NUM_CHANNELS = 3 // RGB
|
|
19
19
|
private static let NUM_CLASSES = 2 // blur, sharp
|
|
@@ -27,10 +27,10 @@ class BlurDetectionHelper {
|
|
|
27
27
|
private static let AT_LEAST_N_PERCENT_OF_AVERAGE_CONFIDENCE: Double = 0.85 // 85% of average confidence
|
|
28
28
|
|
|
29
29
|
// Method based confidence threshold
|
|
30
|
-
private static let MIN_SHARP_CONFIDENCE_FOR_OBJECT_DETECTION: Double = 0.
|
|
31
|
-
private static let MIN_SHARP_CONFIDENCE_FOR_TEXT_DETECTION: Double = 0.
|
|
32
|
-
private static let MIN_SHARP_CONFIDENCE_FOR_FULL_IMAGE: Double = 0.
|
|
33
|
-
|
|
30
|
+
private static let MIN_SHARP_CONFIDENCE_FOR_OBJECT_DETECTION: Double = 0.75 // 75% confidence threshold
|
|
31
|
+
private static let MIN_SHARP_CONFIDENCE_FOR_TEXT_DETECTION: Double = 0.15 // 15% confidence threshold
|
|
32
|
+
private static let MIN_SHARP_CONFIDENCE_FOR_FULL_IMAGE: Double = 0.75 // 75% confidence threshold
|
|
33
|
+
|
|
34
34
|
private var interpreter: Interpreter?
|
|
35
35
|
private var isInitialized = false
|
|
36
36
|
|
|
@@ -391,11 +391,37 @@ class BlurDetectionHelper {
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
/**
|
|
394
|
-
* Resize image to target size
|
|
394
|
+
* Resize image to target size while maintaining aspect ratio
|
|
395
395
|
*/
|
|
396
396
|
private func resizeImage(_ image: UIImage, to size: CGSize) -> UIImage? {
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
let targetSize = size
|
|
398
|
+
let imageSize = image.size
|
|
399
|
+
|
|
400
|
+
// Calculate aspect ratio preserving dimensions
|
|
401
|
+
let widthRatio = targetSize.width / imageSize.width
|
|
402
|
+
let heightRatio = targetSize.height / imageSize.height
|
|
403
|
+
let scaleFactor = min(widthRatio, heightRatio)
|
|
404
|
+
|
|
405
|
+
let scaledSize = CGSize(
|
|
406
|
+
width: imageSize.width * scaleFactor,
|
|
407
|
+
height: imageSize.height * scaleFactor
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
// Create a square canvas with the target size
|
|
411
|
+
UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0)
|
|
412
|
+
|
|
413
|
+
// Calculate position to center the scaled image
|
|
414
|
+
let x = (targetSize.width - scaledSize.width) / 2
|
|
415
|
+
let y = (targetSize.height - scaledSize.height) / 2
|
|
416
|
+
let drawRect = CGRect(x: x, y: y, width: scaledSize.width, height: scaledSize.height)
|
|
417
|
+
|
|
418
|
+
// Fill background with black (or white) to pad the image
|
|
419
|
+
UIColor.black.setFill()
|
|
420
|
+
UIRectFill(CGRect(origin: .zero, size: targetSize))
|
|
421
|
+
|
|
422
|
+
// Draw the scaled image centered
|
|
423
|
+
image.draw(in: drawRect)
|
|
424
|
+
|
|
399
425
|
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
|
|
400
426
|
UIGraphicsEndImageContext()
|
|
401
427
|
return resizedImage
|
package/package.json
CHANGED