@mleonard9/vin-scanner 1.2.3 → 1.2.4
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.
- package/android/src/main/java/com/visioncamerabarcodescanner/VisionCameraBarcodeScannerModule.kt +52 -2
- package/android/src/main/java/com/visioncameratextrecognition/VisionCameraTextRecognitionModule.kt +45 -1
- package/ios/VisionCameraBarcodeScanner.m +35 -2
- package/ios/VisionCameraTextRecognition.m +46 -2
- package/lib/commonjs/scanBarcodes.js +16 -4
- package/lib/commonjs/scanBarcodes.js.map +1 -1
- package/lib/commonjs/scanText.js +16 -4
- package/lib/commonjs/scanText.js.map +1 -1
- package/lib/commonjs/useVinScanner.js +32 -8
- package/lib/commonjs/useVinScanner.js.map +1 -1
- package/lib/commonjs/vinUtils.js +26 -16
- package/lib/commonjs/vinUtils.js.map +1 -1
- package/lib/module/scanBarcodes.js +16 -4
- package/lib/module/scanBarcodes.js.map +1 -1
- package/lib/module/scanText.js +16 -4
- package/lib/module/scanText.js.map +1 -1
- package/lib/module/useVinScanner.js +32 -8
- package/lib/module/useVinScanner.js.map +1 -1
- package/lib/module/vinUtils.js +26 -16
- package/lib/module/vinUtils.js.map +1 -1
- package/lib/typescript/src/scanBarcodes.d.ts.map +1 -1
- package/lib/typescript/src/scanText.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +23 -2
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useVinScanner.d.ts.map +1 -1
- package/lib/typescript/src/vinUtils.d.ts +4 -2
- package/lib/typescript/src/vinUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/scanBarcodes.ts +29 -6
- package/src/scanText.ts +33 -9
- package/src/types.ts +28 -3
- package/src/useVinScanner.ts +36 -6
- package/src/vinUtils.ts +25 -19
package/android/src/main/java/com/visioncamerabarcodescanner/VisionCameraBarcodeScannerModule.kt
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.visioncamerabarcodescanner
|
|
2
2
|
|
|
3
|
+
import android.graphics.Rect
|
|
3
4
|
import android.media.Image
|
|
4
5
|
import com.google.android.gms.tasks.Task
|
|
5
6
|
import com.google.android.gms.tasks.Tasks
|
|
@@ -78,6 +79,14 @@ class VisionCameraBarcodeScannerModule(
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
private fun isInRegion(rect: Rect, roi: Rect?): Boolean {
|
|
83
|
+
if (roi == null) return true
|
|
84
|
+
// Check if the detection center is within the ROI
|
|
85
|
+
val centerX = rect.centerX()
|
|
86
|
+
val centerY = rect.centerY()
|
|
87
|
+
return roi.contains(centerX, centerY)
|
|
88
|
+
}
|
|
89
|
+
|
|
81
90
|
override fun callback(frame: Frame, arguments: Map<String, Any>?): Any {
|
|
82
91
|
return try {
|
|
83
92
|
val options = mergedOptions(arguments)
|
|
@@ -89,15 +98,56 @@ class VisionCameraBarcodeScannerModule(
|
|
|
89
98
|
val task: Task<List<Barcode>> = scanner.process(image)
|
|
90
99
|
val barcodes: List<Barcode> = Tasks.await(task)
|
|
91
100
|
|
|
101
|
+
// Region of Interest processing
|
|
102
|
+
// ROI is passed as fractional coordinates (0.0-1.0) relative to the image size
|
|
103
|
+
var roiRect: Rect? = null
|
|
104
|
+
val roiMap = options["regionOfInterest"] as? Map<*, *>
|
|
105
|
+
if (roiMap != null) {
|
|
106
|
+
val top = (roiMap["top"] as? Double ?: 0.0)
|
|
107
|
+
val left = (roiMap["left"] as? Double ?: 0.0)
|
|
108
|
+
val width = (roiMap["width"] as? Double ?: 1.0)
|
|
109
|
+
val height = (roiMap["height"] as? Double ?: 1.0)
|
|
110
|
+
|
|
111
|
+
// The input image dimensions (rotated)
|
|
112
|
+
// MLKit coordinates match the InputImage dimensions.
|
|
113
|
+
// If we have rotation, we need to be careful.
|
|
114
|
+
// However, for simplicity in V1, let's assume ROI is relative to the *displayed* frame
|
|
115
|
+
// which matches MLKit's coordinate system after rotation usually?
|
|
116
|
+
// Actually, MLKit reports coordinates in the image's coordinate system.
|
|
117
|
+
// If rotation is 90, width/height swap.
|
|
118
|
+
// Let's use the dimensions from MLKit's InputImage if accessible, or Frame.
|
|
119
|
+
// VisionCamera Frame width/height are oriented.
|
|
120
|
+
|
|
121
|
+
val imgWidth = image.width
|
|
122
|
+
val imgHeight = image.height
|
|
123
|
+
|
|
124
|
+
val rLeft = (left * imgWidth).toInt()
|
|
125
|
+
val rTop = (top * imgHeight).toInt()
|
|
126
|
+
val rRight = rLeft + (width * imgWidth).toInt()
|
|
127
|
+
val rBottom = rTop + (height * imgHeight).toInt()
|
|
128
|
+
|
|
129
|
+
roiRect = Rect(rLeft, rTop, rRight, rBottom)
|
|
130
|
+
}
|
|
131
|
+
|
|
92
132
|
val detections = ArrayList<Map<String, Any?>>()
|
|
133
|
+
// We can't predict exact size if we filter by ROI, but allocating max size is safe for SharedArray
|
|
134
|
+
// Ideally we would compact it, but SharedArray is fixed size.
|
|
135
|
+
// We'll filter in the loop and just leave unused slots at the end (or compact indices).
|
|
136
|
+
// Actually, simpler to just build the list and then write to SharedArray.
|
|
137
|
+
|
|
138
|
+
val filteredBarcodes = barcodes.filter { barcode ->
|
|
139
|
+
val box = barcode.boundingBox
|
|
140
|
+
box == null || isInRegion(box, roiRect)
|
|
141
|
+
}
|
|
142
|
+
|
|
93
143
|
val sharedArray =
|
|
94
|
-
if (
|
|
144
|
+
if (filteredBarcodes.isNotEmpty()) SharedArray(proxy, filteredBarcodes.size * BOX_STRIDE * java.lang.Float.BYTES)
|
|
95
145
|
else null
|
|
96
146
|
val floatBuffer = sharedArray?.byteBuffer
|
|
97
147
|
?.order(ByteOrder.nativeOrder())
|
|
98
148
|
?.asFloatBuffer()
|
|
99
149
|
|
|
100
|
-
|
|
150
|
+
filteredBarcodes.forEachIndexed { index, barcode ->
|
|
101
151
|
val detection = HashMap<String, Any?>()
|
|
102
152
|
detection["rawValue"] = barcode.rawValue
|
|
103
153
|
detection["displayValue"] = barcode.displayValue
|
package/android/src/main/java/com/visioncameratextrecognition/VisionCameraTextRecognitionModule.kt
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.visioncameratextrecognition
|
|
2
2
|
|
|
3
|
+
import android.graphics.Rect
|
|
3
4
|
import android.media.Image
|
|
4
5
|
import com.google.android.gms.tasks.Task
|
|
5
6
|
import com.google.android.gms.tasks.Tasks
|
|
@@ -19,6 +20,7 @@ import com.mrousavy.camera.frameprocessors.VisionCameraProxy
|
|
|
19
20
|
import java.nio.ByteOrder
|
|
20
21
|
import java.util.HashMap
|
|
21
22
|
import java.util.ArrayList
|
|
23
|
+
import java.util.regex.Pattern
|
|
22
24
|
|
|
23
25
|
private const val TEXT_BOX_STRIDE = 12
|
|
24
26
|
|
|
@@ -52,6 +54,12 @@ class VisionCameraTextRecognitionModule(
|
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
private fun isInRegion(rect: Rect?, roi: Rect?): Boolean {
|
|
58
|
+
if (roi == null || rect == null) return true
|
|
59
|
+
// Check if overlap or contained. For VIN scanning, contained center is usually best
|
|
60
|
+
return roi.contains(rect.centerX(), rect.centerY())
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
override fun callback(frame: Frame, arguments: Map<String, Any>?): Any {
|
|
56
64
|
try {
|
|
57
65
|
val mediaImage: Image = frame.image
|
|
@@ -59,15 +67,50 @@ class VisionCameraTextRecognitionModule(
|
|
|
59
67
|
val rotationDegrees = rotationOverride ?: frame.imageProxy.imageInfo.rotationDegrees
|
|
60
68
|
val requestedLanguage = arguments?.get("language")?.toString()?.ifEmpty { null }
|
|
61
69
|
val effectiveLanguage = requestedLanguage ?: language
|
|
70
|
+
val validationPattern = arguments?.get("validationPattern")?.toString()?.ifEmpty { null }
|
|
71
|
+
|
|
62
72
|
val recognizer = recognizerFor(effectiveLanguage)
|
|
63
73
|
val image = InputImage.fromMediaImage(mediaImage, rotationDegrees)
|
|
64
74
|
val task: Task<Text> = recognizer.process(image)
|
|
65
75
|
val result: Text? = Tasks.await(task)
|
|
76
|
+
|
|
66
77
|
val resultText = result?.text
|
|
67
78
|
val detections = ArrayList<Map<String, Any?>>()
|
|
68
79
|
val boxValues = ArrayList<FloatArray>()
|
|
69
80
|
|
|
81
|
+
// Calculate ROI if present
|
|
82
|
+
var roiRect: Rect? = null
|
|
83
|
+
val roiMap = arguments?.get("regionOfInterest") as? Map<*, *>
|
|
84
|
+
if (roiMap != null) {
|
|
85
|
+
val top = (roiMap["top"] as? Double ?: 0.0)
|
|
86
|
+
val left = (roiMap["left"] as? Double ?: 0.0)
|
|
87
|
+
val width = (roiMap["width"] as? Double ?: 1.0)
|
|
88
|
+
val height = (roiMap["height"] as? Double ?: 1.0)
|
|
89
|
+
|
|
90
|
+
val imgWidth = image.width
|
|
91
|
+
val imgHeight = image.height
|
|
92
|
+
|
|
93
|
+
val rLeft = (left * imgWidth).toInt()
|
|
94
|
+
val rTop = (top * imgHeight).toInt()
|
|
95
|
+
val rRight = rLeft + (width * imgWidth).toInt()
|
|
96
|
+
val rBottom = rTop + (height * imgHeight).toInt()
|
|
97
|
+
|
|
98
|
+
roiRect = Rect(rLeft, rTop, rRight, rBottom)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Compile regex if pattern provided
|
|
102
|
+
val pattern = if (validationPattern != null) Pattern.compile(validationPattern) else null
|
|
103
|
+
|
|
70
104
|
result?.textBlocks?.forEach { block ->
|
|
105
|
+
if (!isInRegion(block.boundingBox, roiRect)) return@forEach
|
|
106
|
+
|
|
107
|
+
// Native filtering optimization:
|
|
108
|
+
// If a validation pattern is provided, we check if the block text matches it.
|
|
109
|
+
// If not, we skip it. This significantly reduces bridge traffic.
|
|
110
|
+
if (pattern != null && !pattern.matcher(block.text).find()) {
|
|
111
|
+
return@forEach
|
|
112
|
+
}
|
|
113
|
+
|
|
71
114
|
val blockBounds = block.boundingBox
|
|
72
115
|
if (block.lines.isEmpty()) {
|
|
73
116
|
val detection = HashMap<String, Any?>()
|
|
@@ -93,6 +136,8 @@ class VisionCameraTextRecognitionModule(
|
|
|
93
136
|
)
|
|
94
137
|
}
|
|
95
138
|
block.lines.forEach { line ->
|
|
139
|
+
// Optional: we could also check line bounding box against ROI, but block check is usually sufficient and faster
|
|
140
|
+
|
|
96
141
|
if (line.elements.isEmpty()) {
|
|
97
142
|
val detection = HashMap<String, Any?>()
|
|
98
143
|
detection["resultText"] = resultText
|
|
@@ -171,4 +216,3 @@ class VisionCameraTextRecognitionModule(
|
|
|
171
216
|
}
|
|
172
217
|
}
|
|
173
218
|
}
|
|
174
|
-
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
return self;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
- (BOOL)isRect:(CGRect)rect withinROI:(CGRect)roi {
|
|
41
|
+
// Check if the center of the rect is within the ROI
|
|
42
|
+
CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
|
|
43
|
+
return CGRectContainsPoint(roi, center);
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
- (id _Nullable)callback:(Frame* _Nonnull)frame
|
|
41
47
|
withArguments:(NSDictionary* _Nullable)arguments {
|
|
42
48
|
NSMutableDictionary *config = [self.configuration mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
@@ -84,6 +90,22 @@
|
|
|
84
90
|
image.orientation = correctedOrientation;
|
|
85
91
|
NSMutableArray *detections = [NSMutableArray array];
|
|
86
92
|
__block NSDictionary *resultPayload = @{};
|
|
93
|
+
|
|
94
|
+
// Region of Interest
|
|
95
|
+
NSDictionary *roiConfig = config[@"regionOfInterest"];
|
|
96
|
+
CGRect roiRect = CGRectNull;
|
|
97
|
+
if (roiConfig) {
|
|
98
|
+
CGFloat top = [roiConfig[@"top"] doubleValue];
|
|
99
|
+
CGFloat left = [roiConfig[@"left"] doubleValue];
|
|
100
|
+
CGFloat width = [roiConfig[@"width"] doubleValue];
|
|
101
|
+
CGFloat height = [roiConfig[@"height"] doubleValue];
|
|
102
|
+
|
|
103
|
+
CGFloat imgWidth = CVPixelBufferGetWidth(CMSampleBufferGetImageBuffer(buffer));
|
|
104
|
+
CGFloat imgHeight = CVPixelBufferGetHeight(CMSampleBufferGetImageBuffer(buffer));
|
|
105
|
+
|
|
106
|
+
roiRect = CGRectMake(left * imgWidth, top * imgHeight, width * imgWidth, height * imgHeight);
|
|
107
|
+
}
|
|
108
|
+
|
|
87
109
|
dispatch_group_t dispatchGroup = dispatch_group_create();
|
|
88
110
|
dispatch_group_enter(dispatchGroup);
|
|
89
111
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
@@ -94,15 +116,26 @@
|
|
|
94
116
|
dispatch_group_leave(dispatchGroup);
|
|
95
117
|
return;
|
|
96
118
|
}
|
|
119
|
+
|
|
120
|
+
// Filter barcodes by ROI
|
|
121
|
+
NSMutableArray<MLKBarcode *> *filteredBarcodes = [NSMutableArray array];
|
|
122
|
+
if (barcodes.count > 0) {
|
|
123
|
+
for (MLKBarcode *barcode in barcodes) {
|
|
124
|
+
if (CGRectIsNull(roiRect) || [self isRect:barcode.frame withinROI:roiRect]) {
|
|
125
|
+
[filteredBarcodes addObject:barcode];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
97
130
|
SharedArray *sharedBoxes = nil;
|
|
98
131
|
float *boxData = nil;
|
|
99
|
-
const NSUInteger count =
|
|
132
|
+
const NSUInteger count = filteredBarcodes.count;
|
|
100
133
|
if (count > 0 && self.proxyHolder != nil) {
|
|
101
134
|
sharedBoxes = [[SharedArray alloc] initWithProxy:self.proxyHolder
|
|
102
135
|
allocateWithSize:count * sizeof(float) * 6];
|
|
103
136
|
boxData = (float *)sharedBoxes.data;
|
|
104
137
|
}
|
|
105
|
-
[
|
|
138
|
+
[filteredBarcodes enumerateObjectsUsingBlock:^(MLKBarcode * _Nonnull barcode, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
106
139
|
NSMutableDictionary *obj = [[NSMutableDictionary alloc] init];
|
|
107
140
|
obj[@"displayValue"] = barcode.displayValue ?: (id)kCFNull;
|
|
108
141
|
obj[@"rawValue"] = barcode.rawValue ?: (id)kCFNull;
|
|
@@ -78,6 +78,12 @@
|
|
|
78
78
|
return fallback;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
- (BOOL)isRect:(CGRect)rect withinROI:(CGRect)roi {
|
|
82
|
+
// Check if the center of the rect is within the ROI
|
|
83
|
+
CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
|
|
84
|
+
return CGRectContainsPoint(roi, center);
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
- (id _Nullable)callback:(Frame* _Nonnull)frame
|
|
82
88
|
withArguments:(NSDictionary* _Nullable)arguments {
|
|
83
89
|
CMSampleBufferRef buffer = frame.buffer;
|
|
@@ -112,6 +118,33 @@
|
|
|
112
118
|
NSMutableArray *detections = [NSMutableArray array];
|
|
113
119
|
NSMutableArray<NSArray<NSNumber *> *> *boxValues = [NSMutableArray array];
|
|
114
120
|
NSString *language = arguments[@"language"] ?: self.preferredLanguage ?: @"latin";
|
|
121
|
+
NSString *validationPattern = arguments[@"validationPattern"];
|
|
122
|
+
|
|
123
|
+
// Region of Interest
|
|
124
|
+
NSDictionary *roiConfig = arguments[@"regionOfInterest"];
|
|
125
|
+
CGRect roiRect = CGRectNull;
|
|
126
|
+
if (roiConfig) {
|
|
127
|
+
CGFloat top = [roiConfig[@"top"] doubleValue];
|
|
128
|
+
CGFloat left = [roiConfig[@"left"] doubleValue];
|
|
129
|
+
CGFloat width = [roiConfig[@"width"] doubleValue];
|
|
130
|
+
CGFloat height = [roiConfig[@"height"] doubleValue];
|
|
131
|
+
|
|
132
|
+
CGFloat imgWidth = CVPixelBufferGetWidth(CMSampleBufferGetImageBuffer(buffer));
|
|
133
|
+
CGFloat imgHeight = CVPixelBufferGetHeight(CMSampleBufferGetImageBuffer(buffer));
|
|
134
|
+
|
|
135
|
+
roiRect = CGRectMake(left * imgWidth, top * imgHeight, width * imgWidth, height * imgHeight);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
NSRegularExpression *regex = nil;
|
|
139
|
+
if (validationPattern.length > 0) {
|
|
140
|
+
NSError *regexError = nil;
|
|
141
|
+
regex = [NSRegularExpression regularExpressionWithPattern:validationPattern options:0 error:®exError];
|
|
142
|
+
if (regexError) {
|
|
143
|
+
// Fallback to no regex if invalid
|
|
144
|
+
regex = nil;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
115
148
|
MLKTextRecognizer *recognizer = [self recognizerForLanguage:language];
|
|
116
149
|
dispatch_group_t dispatchGroup = dispatch_group_create();
|
|
117
150
|
dispatch_group_enter(dispatchGroup);
|
|
@@ -125,8 +158,20 @@
|
|
|
125
158
|
}
|
|
126
159
|
NSString *resultText = result.text;
|
|
127
160
|
for (MLKTextBlock *block in result.blocks) {
|
|
161
|
+
// Filter by ROI
|
|
162
|
+
if (!CGRectIsNull(roiRect) && ![self isRect:block.frame withinROI:roiRect]) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Filter by Regex
|
|
167
|
+
if (regex != nil) {
|
|
168
|
+
NSRange range = NSMakeRange(0, block.text.length);
|
|
169
|
+
if ([regex numberOfMatchesInString:block.text options:0 range:range] == 0) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
128
174
|
CGRect blockFrame = block.frame;
|
|
129
|
-
// Coordinates are now correct after orientation fix
|
|
130
175
|
|
|
131
176
|
if (block.lines.count == 0) {
|
|
132
177
|
NSMutableDictionary *entry = [[NSMutableDictionary alloc] init];
|
|
@@ -210,4 +255,3 @@
|
|
|
210
255
|
VISION_EXPORT_FRAME_PROCESSOR(VisionCameraTextRecognitionPlugin, vinScannerText)
|
|
211
256
|
|
|
212
257
|
@end
|
|
213
|
-
|
|
@@ -70,7 +70,7 @@ const normalizeBarcodeDetections = payload => {
|
|
|
70
70
|
return output;
|
|
71
71
|
});
|
|
72
72
|
};
|
|
73
|
-
const mergeArgs = (baseArgs, overrides, orientation) => {
|
|
73
|
+
const mergeArgs = (baseArgs, overrides, orientation, regionOfInterest) => {
|
|
74
74
|
'worklet';
|
|
75
75
|
|
|
76
76
|
const merged = {
|
|
@@ -79,6 +79,7 @@ const mergeArgs = (baseArgs, overrides, orientation) => {
|
|
|
79
79
|
if (overrides) {
|
|
80
80
|
const {
|
|
81
81
|
orientation: overrideOrientation,
|
|
82
|
+
regionOfInterest: overrideRoi,
|
|
82
83
|
...formatMap
|
|
83
84
|
} = overrides;
|
|
84
85
|
Object.entries(formatMap).forEach(([key, value]) => {
|
|
@@ -89,8 +90,18 @@ const mergeArgs = (baseArgs, overrides, orientation) => {
|
|
|
89
90
|
} else if (orientation) {
|
|
90
91
|
merged.orientation = orientation;
|
|
91
92
|
}
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
if (overrideRoi) {
|
|
94
|
+
merged.regionOfInterest = overrideRoi;
|
|
95
|
+
} else if (regionOfInterest) {
|
|
96
|
+
merged.regionOfInterest = regionOfInterest;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
if (orientation) {
|
|
100
|
+
merged.orientation = orientation;
|
|
101
|
+
}
|
|
102
|
+
if (regionOfInterest) {
|
|
103
|
+
merged.regionOfInterest = regionOfInterest;
|
|
104
|
+
}
|
|
94
105
|
}
|
|
95
106
|
return merged;
|
|
96
107
|
};
|
|
@@ -107,7 +118,8 @@ function createBarcodeScannerPlugin(formats) {
|
|
|
107
118
|
'worklet';
|
|
108
119
|
|
|
109
120
|
const orientation = overrides === null || overrides === void 0 ? void 0 : overrides.orientation;
|
|
110
|
-
const
|
|
121
|
+
const regionOfInterest = overrides === null || overrides === void 0 ? void 0 : overrides.regionOfInterest;
|
|
122
|
+
const args = overrides || orientation || regionOfInterest ? mergeArgs(baseOptions, overrides, orientation ?? null, regionOfInterest ?? null) : baseOptions;
|
|
111
123
|
const result = plugin.call(frame, args);
|
|
112
124
|
return normalizeBarcodeDetections(result);
|
|
113
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_reactNativeVisionCamera","LINKING_ERROR","Platform","select","ios","default","DEFAULT_FORMATS","KNOWN_FORMATS","toNativeBarcodeOptions","formats","sanitized","length","includes","all","reduce","acc","format","BOX_STRIDE","toFloat32Array","input","Float32Array","undefined","normalizeBarcodeDetections","payload","Array","isArray","record","detections","buffer","boxes","map","detection","index","output","boxIndex","offset","top","bottom","left","right","width","height","mergeArgs","baseArgs","overrides","orientation","merged","overrideOrientation","formatMap","Object","entries","forEach","key","value","createBarcodeScannerPlugin","baseOptions","plugin","VisionCameraProxy","initFrameProcessorPlugin","Error","scanBarcodes","frame","args","result","call"],"sourceRoot":"../../src","sources":["scanBarcodes.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,wBAAA,GAAAD,OAAA;
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_reactNativeVisionCamera","LINKING_ERROR","Platform","select","ios","default","DEFAULT_FORMATS","KNOWN_FORMATS","toNativeBarcodeOptions","formats","sanitized","length","includes","all","reduce","acc","format","BOX_STRIDE","toFloat32Array","input","Float32Array","undefined","normalizeBarcodeDetections","payload","Array","isArray","record","detections","buffer","boxes","map","detection","index","output","boxIndex","offset","top","bottom","left","right","width","height","mergeArgs","baseArgs","overrides","orientation","regionOfInterest","merged","overrideOrientation","overrideRoi","formatMap","Object","entries","forEach","key","value","createBarcodeScannerPlugin","baseOptions","plugin","VisionCameraProxy","initFrameProcessorPlugin","Error","scanBarcodes","frame","args","result","call"],"sourceRoot":"../../src","sources":["scanBarcodes.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/scanText.js
CHANGED
|
@@ -60,7 +60,7 @@ const normalizeTextDetections = payload => {
|
|
|
60
60
|
return output;
|
|
61
61
|
});
|
|
62
62
|
};
|
|
63
|
-
const mergeTextArgs = (base, overrides, orientation) => {
|
|
63
|
+
const mergeTextArgs = (base, overrides, orientation, regionOfInterest) => {
|
|
64
64
|
'worklet';
|
|
65
65
|
|
|
66
66
|
const merged = {
|
|
@@ -69,6 +69,7 @@ const mergeTextArgs = (base, overrides, orientation) => {
|
|
|
69
69
|
if (overrides) {
|
|
70
70
|
const {
|
|
71
71
|
orientation: overrideOrientation,
|
|
72
|
+
regionOfInterest: overrideRoi,
|
|
72
73
|
...rest
|
|
73
74
|
} = overrides;
|
|
74
75
|
Object.assign(merged, rest);
|
|
@@ -77,8 +78,18 @@ const mergeTextArgs = (base, overrides, orientation) => {
|
|
|
77
78
|
} else if (orientation) {
|
|
78
79
|
merged.orientation = orientation;
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
if (overrideRoi) {
|
|
82
|
+
merged.regionOfInterest = overrideRoi;
|
|
83
|
+
} else if (regionOfInterest) {
|
|
84
|
+
merged.regionOfInterest = regionOfInterest;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
if (orientation) {
|
|
88
|
+
merged.orientation = orientation;
|
|
89
|
+
}
|
|
90
|
+
if (regionOfInterest) {
|
|
91
|
+
merged.regionOfInterest = regionOfInterest;
|
|
92
|
+
}
|
|
82
93
|
}
|
|
83
94
|
return merged;
|
|
84
95
|
};
|
|
@@ -94,7 +105,8 @@ function createTextRecognitionPlugin(options) {
|
|
|
94
105
|
'worklet';
|
|
95
106
|
|
|
96
107
|
const orientation = overrides === null || overrides === void 0 ? void 0 : overrides.orientation;
|
|
97
|
-
const
|
|
108
|
+
const regionOfInterest = overrides === null || overrides === void 0 ? void 0 : overrides.regionOfInterest;
|
|
109
|
+
const args = overrides || orientation || regionOfInterest ? mergeTextArgs(options, overrides, orientation ?? null, regionOfInterest ?? null) : options;
|
|
98
110
|
const result = plugin.call(frame, args);
|
|
99
111
|
return normalizeTextDetections(result);
|
|
100
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_reactNativeVisionCamera","LINKING_ERROR","Platform","select","ios","default","TEXT_BOX_STRIDE","toFloat32Array","input","Float32Array","undefined","normalizeTextDetections","payload","Array","isArray","record","detections","buffer","boxes","map","detection","index","output","boxIndex","offset","length","blockFrameTop","blockFrameBottom","blockFrameLeft","blockFrameRight","lineFrameTop","lineFrameBottom","lineFrameLeft","lineFrameRight","elementFrameTop","elementFrameBottom","elementFrameLeft","elementFrameRight","mergeTextArgs","base","overrides","orientation","merged","overrideOrientation","rest","Object","assign","createTextRecognitionPlugin","options","plugin","VisionCameraProxy","initFrameProcessorPlugin","Error","scanText","frame","args","result","call"],"sourceRoot":"../../src","sources":["scanText.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,wBAAA,GAAAD,OAAA;
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_reactNativeVisionCamera","LINKING_ERROR","Platform","select","ios","default","TEXT_BOX_STRIDE","toFloat32Array","input","Float32Array","undefined","normalizeTextDetections","payload","Array","isArray","record","detections","buffer","boxes","map","detection","index","output","boxIndex","offset","length","blockFrameTop","blockFrameBottom","blockFrameLeft","blockFrameRight","lineFrameTop","lineFrameBottom","lineFrameLeft","lineFrameRight","elementFrameTop","elementFrameBottom","elementFrameLeft","elementFrameRight","mergeTextArgs","base","overrides","orientation","regionOfInterest","merged","overrideOrientation","overrideRoi","rest","Object","assign","createTextRecognitionPlugin","options","plugin","VisionCameraProxy","initFrameProcessorPlugin","Error","scanText","frame","args","result","call"],"sourceRoot":"../../src","sources":["scanText.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -25,7 +25,11 @@ function useVinScanner(options) {
|
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
27
|
return (0, _scanText.createTextRecognitionPlugin)({
|
|
28
|
-
language: resolvedOptions.text.language
|
|
28
|
+
language: resolvedOptions.text.language,
|
|
29
|
+
// We can use a broad validation pattern here to help the native side
|
|
30
|
+
// filter obvious non-VIN text, improving bridge performance.
|
|
31
|
+
// VINs are 17 chars alphanumeric.
|
|
32
|
+
validationPattern: '[A-HJ-NPR-Z0-9]{10,}'
|
|
29
33
|
});
|
|
30
34
|
}, [resolvedOptions.text]);
|
|
31
35
|
const emitResult = (0, _reactNativeWorkletsCore.useRunOnJS)((result, event) => {
|
|
@@ -46,17 +50,37 @@ function useVinScanner(options) {
|
|
|
46
50
|
lastFrameTimestampRef.current = now;
|
|
47
51
|
}
|
|
48
52
|
const orientationOverride = resolvedOptions.detection.forceOrientation ?? null;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
const regionOfInterest = resolvedOptions.detection.regionOfInterest;
|
|
54
|
+
const barcodeArgs = {
|
|
55
|
+
orientation: orientationOverride ?? undefined,
|
|
56
|
+
regionOfInterest
|
|
57
|
+
};
|
|
52
58
|
const barcodes = barcodeScanner ? barcodeScanner.scanBarcodes(frame, barcodeArgs) : [];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
|
|
60
|
+
// Performance Optimization:
|
|
61
|
+
// If we found a valid VIN in the barcode, and we only need the "first" result,
|
|
62
|
+
// skip the expensive text recognition step entirely.
|
|
63
|
+
let hasBarcodeVin = false;
|
|
64
|
+
if (barcodes && barcodes.length > 0) {
|
|
65
|
+
const tempCandidates = (0, _vinUtils.buildVinCandidates)({
|
|
66
|
+
barcodes,
|
|
67
|
+
textBlocks: [],
|
|
68
|
+
timestamp: now
|
|
69
|
+
}, resolvedOptions);
|
|
70
|
+
if (tempCandidates.length > 0) {
|
|
71
|
+
hasBarcodeVin = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const textArgs = {
|
|
75
|
+
orientation: orientationOverride ?? undefined,
|
|
76
|
+
regionOfInterest
|
|
77
|
+
};
|
|
56
78
|
frameCounterRef.current += 1;
|
|
57
79
|
const frameIndex = frameCounterRef.current;
|
|
58
80
|
const textScanInterval = resolvedOptions.detection.textScanInterval;
|
|
59
|
-
const shouldRunText =
|
|
81
|
+
const shouldRunText = !hasBarcodeVin &&
|
|
82
|
+
// Skip if we already have a VIN from barcode
|
|
83
|
+
textScanner && (textScanInterval <= 1 || frameIndex % textScanInterval === 0);
|
|
60
84
|
const textBlocks = shouldRunText && textScanner ? textScanner.scanText(frame, textArgs) : [];
|
|
61
85
|
const payload = {
|
|
62
86
|
barcodes: barcodes ?? [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactNativeVisionCamera","_reactNativeWorkletsCore","_scanBarcodes","_scanText","_vinUtils","useVinScanner","options","resolvedOptions","useMemo","resolveOptions","lastFrameTimestampRef","useRef","frameCounterRef","barcodeScanner","barcode","enabled","createBarcodeScannerPlugin","formats","textScanner","text","createTextRecognitionPlugin","language","emitResult","useRunOnJS","result","event","onResult","frameProcessor","useFrameProcessor","frame","now","timestamp","Date","maxFps","detection","maxFrameRate","minInterval","current","orientationOverride","forceOrientation","barcodeArgs","orientation","undefined","barcodes","scanBarcodes","textArgs","frameIndex","textScanInterval","shouldRunText","
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNativeVisionCamera","_reactNativeWorkletsCore","_scanBarcodes","_scanText","_vinUtils","useVinScanner","options","resolvedOptions","useMemo","resolveOptions","lastFrameTimestampRef","useRef","frameCounterRef","barcodeScanner","barcode","enabled","createBarcodeScannerPlugin","formats","textScanner","text","createTextRecognitionPlugin","language","validationPattern","emitResult","useRunOnJS","result","event","onResult","frameProcessor","useFrameProcessor","frame","now","timestamp","Date","maxFps","detection","maxFrameRate","minInterval","current","orientationOverride","forceOrientation","regionOfInterest","barcodeArgs","orientation","undefined","barcodes","scanBarcodes","hasBarcodeVin","length","tempCandidates","buildVinCandidates","textBlocks","textArgs","frameIndex","textScanInterval","shouldRunText","scanText","payload","candidates","best","pickFirstCandidate","mode","resultMode","normalizedResult","raw"],"sourceRoot":"../../src","sources":["useVinScanner.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/vinUtils.js
CHANGED
|
@@ -34,15 +34,22 @@ const DEFAULT_RESOLVED_OPTIONS = {
|
|
|
34
34
|
resultMode: 'first',
|
|
35
35
|
textScanInterval: 1,
|
|
36
36
|
maxFrameRate: 30,
|
|
37
|
-
forceOrientation: null
|
|
37
|
+
forceOrientation: null,
|
|
38
|
+
regionOfInterest: {
|
|
39
|
+
top: 0,
|
|
40
|
+
left: 0,
|
|
41
|
+
width: 1,
|
|
42
|
+
height: 1
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
45
|
};
|
|
40
46
|
const resolveOptions = options => {
|
|
41
47
|
'worklet';
|
|
42
48
|
|
|
43
|
-
var _options$detection, _options$detection2, _options$barcode, _options$barcode2, _options$text, _options$text2, _options$
|
|
49
|
+
var _options$detection, _options$detection2, _options$detection3, _options$barcode, _options$barcode2, _options$text, _options$text2, _options$detection4, _options$detection5;
|
|
44
50
|
const resultMode = (options === null || options === void 0 || (_options$detection = options.detection) === null || _options$detection === void 0 ? void 0 : _options$detection.resultMode) ?? DEFAULT_RESOLVED_OPTIONS.detection.resultMode;
|
|
45
51
|
const textScanInterval = Math.max(1, (options === null || options === void 0 || (_options$detection2 = options.detection) === null || _options$detection2 === void 0 ? void 0 : _options$detection2.textScanInterval) ?? DEFAULT_RESOLVED_OPTIONS.detection.textScanInterval);
|
|
52
|
+
const regionOfInterest = (options === null || options === void 0 || (_options$detection3 = options.detection) === null || _options$detection3 === void 0 ? void 0 : _options$detection3.regionOfInterest) ?? DEFAULT_RESOLVED_OPTIONS.detection.regionOfInterest;
|
|
46
53
|
return {
|
|
47
54
|
barcode: {
|
|
48
55
|
enabled: (options === null || options === void 0 || (_options$barcode = options.barcode) === null || _options$barcode === void 0 ? void 0 : _options$barcode.enabled) ?? DEFAULT_RESOLVED_OPTIONS.barcode.enabled,
|
|
@@ -55,8 +62,9 @@ const resolveOptions = options => {
|
|
|
55
62
|
detection: {
|
|
56
63
|
resultMode,
|
|
57
64
|
textScanInterval,
|
|
58
|
-
maxFrameRate: (options === null || options === void 0 || (_options$
|
|
59
|
-
forceOrientation: (options === null || options === void 0 || (_options$
|
|
65
|
+
maxFrameRate: (options === null || options === void 0 || (_options$detection4 = options.detection) === null || _options$detection4 === void 0 ? void 0 : _options$detection4.maxFrameRate) ?? DEFAULT_RESOLVED_OPTIONS.detection.maxFrameRate,
|
|
66
|
+
forceOrientation: (options === null || options === void 0 || (_options$detection5 = options.detection) === null || _options$detection5 === void 0 ? void 0 : _options$detection5.forceOrientation) ?? DEFAULT_RESOLVED_OPTIONS.detection.forceOrientation,
|
|
67
|
+
regionOfInterest
|
|
60
68
|
}
|
|
61
69
|
};
|
|
62
70
|
};
|
|
@@ -177,7 +185,7 @@ const extractWithContext = text => {
|
|
|
177
185
|
|
|
178
186
|
// Define patterns inside worklet to ensure they're available in the worklet context
|
|
179
187
|
// Made more flexible to handle: "VIN #", "VIN:", "VIN ", "Serial #:", etc.
|
|
180
|
-
const patterns = [/VIN[\s#:]*([A-Z0-9\s]{17,})/i, /V\.?I\.?N\.?[\s#:]*([A-Z0-9\s]{17,})/i, /Vehicle\s+Identification\s+Number[\s#:]*([A-Z0-9\s]{17,})/i, /Chassis[\s#:]+(?:Number|No\.?|#)?[\s#:]*([A-Z0-9\s]{17,})/i, /Serial[\s#:]+(?:Number|No\.?|#)?[\s#:]*([A-Z0-9\s]{17,})/i];
|
|
188
|
+
const patterns = [/VIN[\s#:]*([A-Z0-9\s]{17,})/i, /V\.?I\.?N\.?[\s#:]*([A-Z0-9\s]{17,})/i, /Vehicle\s+Identification\s+Number[\s#:]*([A-Z0-9\s]{17,})/i, /Chassis[\s#:]+(?:Number|No\.?|#)?[\s#:]*([A-Z0-9\s]{17,})/i, /Serial[\s#:]+(?:Number|No\.?|#)?[\s#:]*([A-Z0-9\s]{17,})/i, /S\/N[\s#:]*([A-Z0-9\s]{17,})/i, /FRAME[\s#:]*([A-Z0-9\s]{17,})/i, /ID[\s#:]*([A-Z0-9\s]{17,})/i];
|
|
181
189
|
patterns.forEach(pattern => {
|
|
182
190
|
const match = pattern.exec(text);
|
|
183
191
|
if (match && match[1]) {
|
|
@@ -247,28 +255,30 @@ const tokenizeCandidate = value => {
|
|
|
247
255
|
};
|
|
248
256
|
|
|
249
257
|
/**
|
|
250
|
-
* Validate World Manufacturer Identifier (WMI)
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* - 2 = Canada
|
|
258
|
+
* Validate World Manufacturer Identifier (WMI).
|
|
259
|
+
*
|
|
260
|
+
* Expanded to cover major international manufacturing regions.
|
|
254
261
|
*
|
|
255
262
|
* @see https://en.wikibooks.org/wiki/Vehicle_Identification_Numbers_(VIN_codes)/World_Manufacturer_Identifier_(WMI)
|
|
256
263
|
*/
|
|
257
|
-
const
|
|
264
|
+
const isValidWmi = value => {
|
|
258
265
|
'worklet';
|
|
259
266
|
|
|
260
267
|
if (value.length < 1) {
|
|
261
268
|
return false;
|
|
262
269
|
}
|
|
263
270
|
const firstChar = value[0];
|
|
264
|
-
|
|
265
|
-
//
|
|
266
|
-
|
|
271
|
+
|
|
272
|
+
// 1-5: North America
|
|
273
|
+
// WZJ: Europe (W: Germany, Z: Italy, J: Japan)
|
|
274
|
+
|
|
275
|
+
// Checking against common valid WMI first characters
|
|
276
|
+
return typeof firstChar === 'string' && /^[1-9JWZ]/.test(firstChar);
|
|
267
277
|
};
|
|
268
278
|
|
|
269
279
|
/**
|
|
270
280
|
* Validate a VIN using ISO 3779 standard
|
|
271
|
-
* Includes checksum validation and
|
|
281
|
+
* Includes checksum validation and WMI validation
|
|
272
282
|
*
|
|
273
283
|
* @see https://en.wikipedia.org/wiki/Vehicle_identification_number
|
|
274
284
|
*/
|
|
@@ -280,8 +290,8 @@ const isValidVin = value => {
|
|
|
280
290
|
return false;
|
|
281
291
|
}
|
|
282
292
|
|
|
283
|
-
// Validate
|
|
284
|
-
if (!
|
|
293
|
+
// Validate WMI
|
|
294
|
+
if (!isValidWmi(value)) {
|
|
285
295
|
return false;
|
|
286
296
|
}
|
|
287
297
|
|