react-native-rectangle-doc-scanner 0.5.0 → 0.7.0
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/dist/DocScanner.js +25 -0
- package/package.json +1 -1
- package/src/DocScanner.tsx +26 -0
package/dist/DocScanner.js
CHANGED
|
@@ -78,12 +78,20 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
78
78
|
requestPermission();
|
|
79
79
|
}, [requestPermission]);
|
|
80
80
|
const updateQuad = (0, react_native_worklets_core_1.useRunOnJS)((value) => {
|
|
81
|
+
if (__DEV__) {
|
|
82
|
+
console.log('[DocScanner] quad', value);
|
|
83
|
+
}
|
|
81
84
|
setQuad(value);
|
|
82
85
|
}, []);
|
|
83
86
|
const reportError = (0, react_native_worklets_core_1.useRunOnJS)((step, error) => {
|
|
84
87
|
const message = error instanceof Error ? error.message : `${error}`;
|
|
85
88
|
console.warn(`[DocScanner] frame error at ${step}: ${message}`);
|
|
86
89
|
}, []);
|
|
90
|
+
const reportStage = (0, react_native_worklets_core_1.useRunOnJS)((stage) => {
|
|
91
|
+
if (__DEV__) {
|
|
92
|
+
console.log('[DocScanner] stage', stage);
|
|
93
|
+
}
|
|
94
|
+
}, []);
|
|
87
95
|
const frameProcessor = (0, react_native_vision_camera_1.useFrameProcessor)((frame) => {
|
|
88
96
|
'worklet';
|
|
89
97
|
let step = 'start';
|
|
@@ -92,53 +100,68 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
92
100
|
const width = Math.floor(frame.width * ratio);
|
|
93
101
|
const height = Math.floor(frame.height * ratio);
|
|
94
102
|
step = 'resize';
|
|
103
|
+
reportStage(step);
|
|
95
104
|
const resized = resize(frame, {
|
|
96
105
|
dataType: 'uint8',
|
|
97
106
|
pixelFormat: 'bgr',
|
|
98
107
|
scale: { width: width, height: height },
|
|
99
108
|
});
|
|
100
109
|
step = 'frameBufferToMat';
|
|
110
|
+
reportStage(step);
|
|
101
111
|
const mat = react_native_fast_opencv_1.OpenCV.frameBufferToMat(height, width, 3, resized);
|
|
102
112
|
step = 'cvtColor';
|
|
113
|
+
reportStage(step);
|
|
103
114
|
react_native_fast_opencv_1.OpenCV.invoke('cvtColor', mat, mat, react_native_fast_opencv_1.ColorConversionCodes.COLOR_BGR2GRAY);
|
|
104
115
|
const morphologyKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
105
116
|
step = 'getStructuringElement';
|
|
117
|
+
reportStage(step);
|
|
106
118
|
const element = react_native_fast_opencv_1.OpenCV.invoke('getStructuringElement', react_native_fast_opencv_1.MorphShapes.MORPH_RECT, morphologyKernel);
|
|
107
119
|
step = 'morphologyEx';
|
|
120
|
+
reportStage(step);
|
|
108
121
|
react_native_fast_opencv_1.OpenCV.invoke('morphologyEx', mat, mat, react_native_fast_opencv_1.MorphTypes.MORPH_OPEN, element);
|
|
109
122
|
const gaussianKernel = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.Size, 5, 5);
|
|
110
123
|
step = 'GaussianBlur';
|
|
124
|
+
reportStage(step);
|
|
111
125
|
react_native_fast_opencv_1.OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
112
126
|
step = 'Canny';
|
|
127
|
+
reportStage(step);
|
|
113
128
|
react_native_fast_opencv_1.OpenCV.invoke('Canny', mat, mat, 75, 100);
|
|
114
129
|
step = 'createContours';
|
|
130
|
+
reportStage(step);
|
|
115
131
|
const contours = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVectorOfVectors);
|
|
116
132
|
react_native_fast_opencv_1.OpenCV.invoke('findContours', mat, contours, react_native_fast_opencv_1.RetrievalModes.RETR_LIST, react_native_fast_opencv_1.ContourApproximationModes.CHAIN_APPROX_SIMPLE);
|
|
117
133
|
let best = null;
|
|
118
134
|
let maxArea = 0;
|
|
119
135
|
step = 'toJSValue';
|
|
136
|
+
reportStage(step);
|
|
120
137
|
const contourVector = react_native_fast_opencv_1.OpenCV.toJSValue(contours);
|
|
121
138
|
const contourArray = Array.isArray(contourVector?.array) ? contourVector.array : [];
|
|
122
139
|
for (let i = 0; i < contourArray.length; i += 1) {
|
|
123
140
|
step = `contour_${i}_copy`;
|
|
141
|
+
reportStage(step);
|
|
124
142
|
const contour = react_native_fast_opencv_1.OpenCV.copyObjectFromVector(contours, i);
|
|
125
143
|
step = `contour_${i}_area`;
|
|
144
|
+
reportStage(step);
|
|
126
145
|
const { value: area } = react_native_fast_opencv_1.OpenCV.invoke('contourArea', contour, false);
|
|
127
146
|
if (area < width * height * 0.1) {
|
|
128
147
|
continue;
|
|
129
148
|
}
|
|
130
149
|
step = `contour_${i}_arcLength`;
|
|
150
|
+
reportStage(step);
|
|
131
151
|
const { value: perimeter } = react_native_fast_opencv_1.OpenCV.invoke('arcLength', contour, true);
|
|
132
152
|
const approx = react_native_fast_opencv_1.OpenCV.createObject(react_native_fast_opencv_1.ObjectType.PointVector);
|
|
133
153
|
step = `contour_${i}_approxPolyDP`;
|
|
154
|
+
reportStage(step);
|
|
134
155
|
react_native_fast_opencv_1.OpenCV.invoke('approxPolyDP', contour, approx, 0.02 * perimeter, true);
|
|
135
156
|
step = `contour_${i}_toJS`;
|
|
157
|
+
reportStage(step);
|
|
136
158
|
const approxValue = react_native_fast_opencv_1.OpenCV.toJSValue(approx);
|
|
137
159
|
const approxArray = Array.isArray(approxValue?.array) ? approxValue.array : [];
|
|
138
160
|
if (approxArray.length !== 4) {
|
|
139
161
|
continue;
|
|
140
162
|
}
|
|
141
163
|
step = `contour_${i}_convex`;
|
|
164
|
+
reportStage(step);
|
|
142
165
|
const points = approxArray.map((pt) => ({
|
|
143
166
|
x: pt.x / ratio,
|
|
144
167
|
y: pt.y / ratio,
|
|
@@ -152,8 +175,10 @@ const DocScanner = ({ onCapture, overlayColor = '#e7a649', autoCapture = true, m
|
|
|
152
175
|
}
|
|
153
176
|
}
|
|
154
177
|
step = 'clearBuffers';
|
|
178
|
+
reportStage(step);
|
|
155
179
|
react_native_fast_opencv_1.OpenCV.clearBuffers();
|
|
156
180
|
step = 'updateQuad';
|
|
181
|
+
reportStage(step);
|
|
157
182
|
updateQuad(best);
|
|
158
183
|
}
|
|
159
184
|
catch (error) {
|
package/package.json
CHANGED
package/src/DocScanner.tsx
CHANGED
|
@@ -83,6 +83,9 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
83
83
|
}, [requestPermission]);
|
|
84
84
|
|
|
85
85
|
const updateQuad = useRunOnJS((value: Point[] | null) => {
|
|
86
|
+
if (__DEV__) {
|
|
87
|
+
console.log('[DocScanner] quad', value);
|
|
88
|
+
}
|
|
86
89
|
setQuad(value);
|
|
87
90
|
}, []);
|
|
88
91
|
|
|
@@ -91,6 +94,12 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
91
94
|
console.warn(`[DocScanner] frame error at ${step}: ${message}`);
|
|
92
95
|
}, []);
|
|
93
96
|
|
|
97
|
+
const reportStage = useRunOnJS((stage: string) => {
|
|
98
|
+
if (__DEV__) {
|
|
99
|
+
console.log('[DocScanner] stage', stage);
|
|
100
|
+
}
|
|
101
|
+
}, []);
|
|
102
|
+
|
|
94
103
|
const frameProcessor = useFrameProcessor((frame) => {
|
|
95
104
|
'worklet';
|
|
96
105
|
|
|
@@ -101,6 +110,7 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
101
110
|
const width = Math.floor(frame.width * ratio);
|
|
102
111
|
const height = Math.floor(frame.height * ratio);
|
|
103
112
|
step = 'resize';
|
|
113
|
+
reportStage(step);
|
|
104
114
|
const resized = resize(frame, {
|
|
105
115
|
dataType: 'uint8',
|
|
106
116
|
pixelFormat: 'bgr',
|
|
@@ -108,24 +118,31 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
108
118
|
});
|
|
109
119
|
|
|
110
120
|
step = 'frameBufferToMat';
|
|
121
|
+
reportStage(step);
|
|
111
122
|
const mat = OpenCV.frameBufferToMat(height, width, 3, resized);
|
|
112
123
|
|
|
113
124
|
step = 'cvtColor';
|
|
125
|
+
reportStage(step);
|
|
114
126
|
OpenCV.invoke('cvtColor', mat, mat, ColorConversionCodes.COLOR_BGR2GRAY);
|
|
115
127
|
|
|
116
128
|
const morphologyKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
117
129
|
step = 'getStructuringElement';
|
|
130
|
+
reportStage(step);
|
|
118
131
|
const element = OpenCV.invoke('getStructuringElement', MorphShapes.MORPH_RECT, morphologyKernel);
|
|
119
132
|
step = 'morphologyEx';
|
|
133
|
+
reportStage(step);
|
|
120
134
|
OpenCV.invoke('morphologyEx', mat, mat, MorphTypes.MORPH_OPEN, element);
|
|
121
135
|
|
|
122
136
|
const gaussianKernel = OpenCV.createObject(ObjectType.Size, 5, 5);
|
|
123
137
|
step = 'GaussianBlur';
|
|
138
|
+
reportStage(step);
|
|
124
139
|
OpenCV.invoke('GaussianBlur', mat, mat, gaussianKernel, 0);
|
|
125
140
|
step = 'Canny';
|
|
141
|
+
reportStage(step);
|
|
126
142
|
OpenCV.invoke('Canny', mat, mat, 75, 100);
|
|
127
143
|
|
|
128
144
|
step = 'createContours';
|
|
145
|
+
reportStage(step);
|
|
129
146
|
const contours = OpenCV.createObject(ObjectType.PointVectorOfVectors);
|
|
130
147
|
OpenCV.invoke('findContours', mat, contours, RetrievalModes.RETR_LIST, ContourApproximationModes.CHAIN_APPROX_SIMPLE);
|
|
131
148
|
|
|
@@ -133,14 +150,17 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
133
150
|
let maxArea = 0;
|
|
134
151
|
|
|
135
152
|
step = 'toJSValue';
|
|
153
|
+
reportStage(step);
|
|
136
154
|
const contourVector = OpenCV.toJSValue(contours);
|
|
137
155
|
const contourArray = Array.isArray(contourVector?.array) ? contourVector.array : [];
|
|
138
156
|
|
|
139
157
|
for (let i = 0; i < contourArray.length; i += 1) {
|
|
140
158
|
step = `contour_${i}_copy`;
|
|
159
|
+
reportStage(step);
|
|
141
160
|
const contour = OpenCV.copyObjectFromVector(contours, i);
|
|
142
161
|
|
|
143
162
|
step = `contour_${i}_area`;
|
|
163
|
+
reportStage(step);
|
|
144
164
|
const { value: area } = OpenCV.invoke('contourArea', contour, false);
|
|
145
165
|
|
|
146
166
|
if (area < width * height * 0.1) {
|
|
@@ -148,13 +168,16 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
148
168
|
}
|
|
149
169
|
|
|
150
170
|
step = `contour_${i}_arcLength`;
|
|
171
|
+
reportStage(step);
|
|
151
172
|
const { value: perimeter } = OpenCV.invoke('arcLength', contour, true);
|
|
152
173
|
const approx = OpenCV.createObject(ObjectType.PointVector);
|
|
153
174
|
|
|
154
175
|
step = `contour_${i}_approxPolyDP`;
|
|
176
|
+
reportStage(step);
|
|
155
177
|
OpenCV.invoke('approxPolyDP', contour, approx, 0.02 * perimeter, true);
|
|
156
178
|
|
|
157
179
|
step = `contour_${i}_toJS`;
|
|
180
|
+
reportStage(step);
|
|
158
181
|
const approxValue = OpenCV.toJSValue(approx);
|
|
159
182
|
const approxArray = Array.isArray(approxValue?.array) ? approxValue.array : [];
|
|
160
183
|
|
|
@@ -163,6 +186,7 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
163
186
|
}
|
|
164
187
|
|
|
165
188
|
step = `contour_${i}_convex`;
|
|
189
|
+
reportStage(step);
|
|
166
190
|
const points: Point[] = approxArray.map((pt: { x: number; y: number }) => ({
|
|
167
191
|
x: pt.x / ratio,
|
|
168
192
|
y: pt.y / ratio,
|
|
@@ -179,8 +203,10 @@ export const DocScanner: React.FC<Props> = ({
|
|
|
179
203
|
}
|
|
180
204
|
|
|
181
205
|
step = 'clearBuffers';
|
|
206
|
+
reportStage(step);
|
|
182
207
|
OpenCV.clearBuffers();
|
|
183
208
|
step = 'updateQuad';
|
|
209
|
+
reportStage(step);
|
|
184
210
|
updateQuad(best);
|
|
185
211
|
} catch (error) {
|
|
186
212
|
reportError(step, error);
|