jscanify 1.2.0 → 1.3.1
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/README.md +7 -4
- package/docs/images/test/test10.jpg +0 -0
- package/docs/images/test/test3.jpg +0 -0
- package/docs/images/test/test4.jpg +0 -0
- package/docs/images/test/test5.jpg +0 -0
- package/docs/images/test/test6.jpg +0 -0
- package/docs/images/test/test7.jpg +0 -0
- package/docs/images/test/test8.jpg +0 -0
- package/docs/images/test/test9.jpg +0 -0
- package/docs/index.css +141 -141
- package/docs/index.html +123 -124
- package/docs/script.js +41 -41
- package/docs/tester.html +148 -0
- package/package.json +32 -32
- package/src/jscanify-node.js +6 -5
- package/src/jscanify.js +255 -254
- package/src/opencv.js +47 -47
- package/test/tests.js +55 -38
package/docs/script.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
let loadedOpenCV = false
|
|
2
|
-
|
|
3
|
-
const openCvURL = "https://docs.opencv.org/4.7.0/opencv.js"
|
|
4
|
-
|
|
5
|
-
function loadOpenCV(onComplete) {
|
|
6
|
-
if (loadedOpenCV) {
|
|
7
|
-
onComplete()
|
|
8
|
-
} else {
|
|
9
|
-
$('#demo-result').text('Loading OpenCV...')
|
|
10
|
-
const script = document.createElement("script")
|
|
11
|
-
script.src = openCvURL
|
|
12
|
-
|
|
13
|
-
script.onload = function () {
|
|
14
|
-
setTimeout(function () {
|
|
15
|
-
onComplete()
|
|
16
|
-
}, 1000)
|
|
17
|
-
loadedOpenCV = true
|
|
18
|
-
}
|
|
19
|
-
document.body.appendChild(script)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const scanner = new jscanify()
|
|
24
|
-
$('#demo-images .image-container').click(function () {
|
|
25
|
-
$('.image-container.selected').removeClass('selected')
|
|
26
|
-
$(this).addClass('selected')
|
|
27
|
-
const imageSrc = $(this).find('img').data('url')
|
|
28
|
-
loadOpenCV(function () {
|
|
29
|
-
$('#demo-result').empty()
|
|
30
|
-
|
|
31
|
-
const newImg = document.createElement("img")
|
|
32
|
-
newImg.src = imageSrc
|
|
33
|
-
|
|
34
|
-
newImg.onload = function(){
|
|
35
|
-
const resultCanvas = scanner.extractPaper(newImg, 386, 500);
|
|
36
|
-
$('#demo-result').append(resultCanvas);
|
|
37
|
-
|
|
38
|
-
const highlightedCanvas = scanner.highlightPaper(newImg)
|
|
39
|
-
$('#demo-result').append(highlightedCanvas);
|
|
40
|
-
}
|
|
41
|
-
})
|
|
1
|
+
let loadedOpenCV = false
|
|
2
|
+
|
|
3
|
+
const openCvURL = "https://docs.opencv.org/4.7.0/opencv.js"
|
|
4
|
+
|
|
5
|
+
function loadOpenCV(onComplete) {
|
|
6
|
+
if (loadedOpenCV) {
|
|
7
|
+
onComplete()
|
|
8
|
+
} else {
|
|
9
|
+
$('#demo-result').text('Loading OpenCV...')
|
|
10
|
+
const script = document.createElement("script")
|
|
11
|
+
script.src = openCvURL
|
|
12
|
+
|
|
13
|
+
script.onload = function () {
|
|
14
|
+
setTimeout(function () {
|
|
15
|
+
onComplete()
|
|
16
|
+
}, 1000)
|
|
17
|
+
loadedOpenCV = true
|
|
18
|
+
}
|
|
19
|
+
document.body.appendChild(script)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const scanner = new jscanify()
|
|
24
|
+
$('#demo-images .image-container').click(function () {
|
|
25
|
+
$('.image-container.selected').removeClass('selected')
|
|
26
|
+
$(this).addClass('selected')
|
|
27
|
+
const imageSrc = $(this).find('img').data('url')
|
|
28
|
+
loadOpenCV(function () {
|
|
29
|
+
$('#demo-result').empty()
|
|
30
|
+
|
|
31
|
+
const newImg = document.createElement("img")
|
|
32
|
+
newImg.src = imageSrc
|
|
33
|
+
|
|
34
|
+
newImg.onload = function(){
|
|
35
|
+
const resultCanvas = scanner.extractPaper(newImg, 386, 500);
|
|
36
|
+
$('#demo-result').append(resultCanvas);
|
|
37
|
+
|
|
38
|
+
const highlightedCanvas = scanner.highlightPaper(newImg)
|
|
39
|
+
$('#demo-result').append(highlightedCanvas);
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
42
|
})
|
package/docs/tester.html
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<script
|
|
5
|
+
async
|
|
6
|
+
src="https://www.googletagmanager.com/gtag/js?id=G-32CWY3SB1G"
|
|
7
|
+
></script>
|
|
8
|
+
<script>
|
|
9
|
+
function gtag() {
|
|
10
|
+
dataLayer.push(arguments);
|
|
11
|
+
}
|
|
12
|
+
(window.dataLayer = window.dataLayer || []),
|
|
13
|
+
gtag("js", new Date()),
|
|
14
|
+
gtag("config", "G-32CWY3SB1G");
|
|
15
|
+
</script>
|
|
16
|
+
<meta charset="UTF-8" />
|
|
17
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
19
|
+
<title>jscanify debugger tool</title>
|
|
20
|
+
<meta
|
|
21
|
+
name="description"
|
|
22
|
+
content="A debugging tool for developers to test jscanify."
|
|
23
|
+
/>
|
|
24
|
+
<meta property="og:title" content="jscanify debugger tool" />
|
|
25
|
+
<meta
|
|
26
|
+
property="og:description"
|
|
27
|
+
content="A debugging tool for developers to test jscanify."
|
|
28
|
+
/>
|
|
29
|
+
<meta
|
|
30
|
+
property="og:url"
|
|
31
|
+
content="https://colonelparrot.github.io/jscanify/tester.html"
|
|
32
|
+
/>
|
|
33
|
+
<meta
|
|
34
|
+
property="og:image"
|
|
35
|
+
content="https://colonelparrot.github.io/jscanify/images/logo.png"
|
|
36
|
+
/>
|
|
37
|
+
<meta property="og:locale" content="en_US" />
|
|
38
|
+
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
|
39
|
+
<style>
|
|
40
|
+
html,
|
|
41
|
+
body {
|
|
42
|
+
margin: 0;
|
|
43
|
+
}
|
|
44
|
+
* {
|
|
45
|
+
font-family: system-ui;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
h1,
|
|
49
|
+
h2,
|
|
50
|
+
h3 {
|
|
51
|
+
font-weight: 400;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
img,
|
|
55
|
+
canvas {
|
|
56
|
+
max-height: 400px;
|
|
57
|
+
max-width: 400px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#results > div {
|
|
61
|
+
margin: 20px;
|
|
62
|
+
margin-top: 0;
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
</head>
|
|
66
|
+
<body>
|
|
67
|
+
<div style="padding: 30px">
|
|
68
|
+
<h1 style="margin: 0">jscanify debugging tool</h1>
|
|
69
|
+
<h2 style="margin-top: 10px">
|
|
70
|
+
A tool for developers to test jscanify on test images
|
|
71
|
+
</h2>
|
|
72
|
+
|
|
73
|
+
<h3 style="margin-bottom: 10px">Upload your image:</h3>
|
|
74
|
+
<input
|
|
75
|
+
type="file"
|
|
76
|
+
id="fileInput"
|
|
77
|
+
accept="image/png, image/gif, image/jpeg"
|
|
78
|
+
/>
|
|
79
|
+
|
|
80
|
+
<div id="result" style="margin-top: 50px; display: none">
|
|
81
|
+
<h2 style="margin-bottom: 0; margin-left: 20px">Result</h2>
|
|
82
|
+
<div style="display: flex; flex-wrap: wrap" id="results">
|
|
83
|
+
<div>
|
|
84
|
+
<h3>Original image</h3>
|
|
85
|
+
<img id="orig" />
|
|
86
|
+
</div>
|
|
87
|
+
<div id="highlighted">
|
|
88
|
+
<h3>Highlighted Paper</h3>
|
|
89
|
+
</div>
|
|
90
|
+
<div id="extracted">
|
|
91
|
+
<h3>Extracted Paper</h3>
|
|
92
|
+
</div>
|
|
93
|
+
<div id="cornerPts">
|
|
94
|
+
<h3>Corner Points</h3>
|
|
95
|
+
<pre style="font-family: monospace"></pre>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div style="margin-top: 50px">
|
|
100
|
+
Check out the code for this page
|
|
101
|
+
<a
|
|
102
|
+
href="https://github.com/ColonelParrot/jscanify/blob/master/docs/tester.html"
|
|
103
|
+
target="_blank"
|
|
104
|
+
>here.</a
|
|
105
|
+
>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<script src="https://docs.opencv.org/4.7.0/opencv.js" async></script>
|
|
110
|
+
<!-- warning: loading OpenCV can take some time. Load asynchronously -->
|
|
111
|
+
<script src="https://cdn.jsdelivr.net/gh/ColonelParrot/jscanify@master/src/jscanify.min.js"></script>
|
|
112
|
+
<script>
|
|
113
|
+
window.addEventListener("load", function () {
|
|
114
|
+
const scanner = new jscanify();
|
|
115
|
+
fileInput.addEventListener("change", function (e) {
|
|
116
|
+
if (e.target.files.length) {
|
|
117
|
+
const image = e.target.files[0];
|
|
118
|
+
orig.src = URL.createObjectURL(image);
|
|
119
|
+
clearData();
|
|
120
|
+
result.style.display = "block";
|
|
121
|
+
|
|
122
|
+
orig.onload = function () {
|
|
123
|
+
const highlightedCanvas = scanner.highlightPaper(orig);
|
|
124
|
+
highlighted.appendChild(highlightedCanvas);
|
|
125
|
+
|
|
126
|
+
const extractedCanvas = scanner.extractPaper(orig, 772, 1000);
|
|
127
|
+
extracted.appendChild(extractedCanvas);
|
|
128
|
+
|
|
129
|
+
const contour = scanner.findPaperContour(cv.imread(orig));
|
|
130
|
+
const cornerPoints = scanner.getCornerPoints(contour);
|
|
131
|
+
cornerPts.querySelector("pre").textContent = JSON.stringify(
|
|
132
|
+
cornerPoints,
|
|
133
|
+
null,
|
|
134
|
+
4
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
function clearData() {
|
|
142
|
+
highlighted.querySelector("canvas")?.remove();
|
|
143
|
+
extracted.querySelector("canvas")?.remove();
|
|
144
|
+
cornerPts.querySelector("pre").textContent = "";
|
|
145
|
+
}
|
|
146
|
+
</script>
|
|
147
|
+
</body>
|
|
148
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "jscanify",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Open-source Javascript mobile document scanner.",
|
|
5
|
-
"main": "src/jscanify-node.js",
|
|
6
|
-
"directories": {
|
|
7
|
-
"doc": "docs"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "mocha"
|
|
11
|
-
},
|
|
12
|
-
"repository": {
|
|
13
|
-
"type": "git",
|
|
14
|
-
"url": "https://github.com/
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"js",
|
|
18
|
-
"scanner",
|
|
19
|
-
"document-scanner"
|
|
20
|
-
],
|
|
21
|
-
"author": "ColonelParrot",
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"bugs": {
|
|
24
|
-
"url": "https://github.com/
|
|
25
|
-
},
|
|
26
|
-
"homepage": "https://colonelparrot.github.io/jscanify/",
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"canvas": "^2.11.2",
|
|
29
|
-
"jsdom": "^22.0.0",
|
|
30
|
-
"mocha": "^10.2.0"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "jscanify",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "Open-source Javascript mobile document scanner.",
|
|
5
|
+
"main": "src/jscanify-node.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"doc": "docs"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "mocha --trace-uncaught"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/puffinsoft/jscanify.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"js",
|
|
18
|
+
"scanner",
|
|
19
|
+
"document-scanner"
|
|
20
|
+
],
|
|
21
|
+
"author": "ColonelParrot",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/puffinsoft/jscanify/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://colonelparrot.github.io/jscanify/",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"canvas": "^2.11.2",
|
|
29
|
+
"jsdom": "^22.0.0",
|
|
30
|
+
"mocha": "^10.2.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/jscanify-node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! jscanify v1.
|
|
1
|
+
/*! jscanify v1.3.1 | (c) ColonelParrot and other contributors | MIT License */
|
|
2
2
|
|
|
3
3
|
const { Canvas, createCanvas, Image, ImageData } = require("canvas");
|
|
4
4
|
const { JSDOM } = require("jsdom");
|
|
@@ -22,7 +22,7 @@ let cv;
|
|
|
22
22
|
* @returns distance between two points
|
|
23
23
|
*/
|
|
24
24
|
function distance(p1, p2) {
|
|
25
|
-
return Math.
|
|
25
|
+
return Math.hypot(p1.x - p2.x, p1.y - p2.y);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
class jscanify {
|
|
@@ -44,13 +44,13 @@ class jscanify {
|
|
|
44
44
|
*/
|
|
45
45
|
findPaperContour(img) {
|
|
46
46
|
const imgGray = new cv.Mat();
|
|
47
|
-
cv.
|
|
47
|
+
cv.Canny(img, imgGray, 50, 200);
|
|
48
48
|
|
|
49
49
|
const imgBlur = new cv.Mat();
|
|
50
50
|
cv.GaussianBlur(
|
|
51
51
|
imgGray,
|
|
52
52
|
imgBlur,
|
|
53
|
-
new cv.Size(
|
|
53
|
+
new cv.Size(3, 3),
|
|
54
54
|
0,
|
|
55
55
|
0,
|
|
56
56
|
cv.BORDER_DEFAULT
|
|
@@ -69,6 +69,7 @@ class jscanify {
|
|
|
69
69
|
cv.RETR_CCOMP,
|
|
70
70
|
cv.CHAIN_APPROX_SIMPLE
|
|
71
71
|
);
|
|
72
|
+
|
|
72
73
|
let maxArea = 0;
|
|
73
74
|
let maxContourIndex = -1;
|
|
74
75
|
for (let i = 0; i < contours.size(); ++i) {
|
|
@@ -140,8 +141,8 @@ class jscanify {
|
|
|
140
141
|
* @param {*} image image to process
|
|
141
142
|
* @param {*} resultWidth desired result paper width
|
|
142
143
|
* @param {*} resultHeight desired result paper height
|
|
143
|
-
* @param {*} onComplete callback with `HTMLCanvasElement` passed - the unwarped paper
|
|
144
144
|
* @param {*} cornerPoints optional custom corner points, in case automatic corner points are incorrect
|
|
145
|
+
* @returns `HTMLCanvasElement` containing undistorted image
|
|
145
146
|
*/
|
|
146
147
|
extractPaper(image, resultWidth, resultHeight, cornerPoints) {
|
|
147
148
|
const canvas = createCanvas();
|