Compare commits

..

18 Commits

Author SHA1 Message Date
ColonelParrot
1138b6216e
Update README.md 2025-01-27 20:05:13 -05:00
ColonelParrot
04b2d3a4c5 bump for npm 2025-01-27 19:56:16 -05:00
ColonelParrot
78ab8fceb6 fix typo 2025-01-27 18:40:29 -05:00
ColonelParrot
d0687658c7 update feature list 2025-01-27 18:38:11 -05:00
ColonelParrot
976ff20489 Modernize 2025-01-27 18:22:17 -05:00
ColonelParrot
ccb883656e Modernize readme 2025-01-27 17:56:09 -05:00
ColonelParrot
6c218b974d height update 2025-01-27 17:11:21 -05:00
ColonelParrot
7a01112dfc update readme logo 2025-01-27 17:10:32 -05:00
ColonelParrot
a742946aa2 website style changes 2025-01-27 17:01:22 -05:00
ColonelParrot
4dd40c2b8f Logo change 2025-01-27 16:57:21 -05:00
ColonelParrot
81cc013b83 fix license link 2025-01-27 16:39:27 -05:00
ColonelParrot
e45ad55c3e Bump to v1.3.1 2025-01-27 16:37:28 -05:00
ColonelParrot
e8e86830e9 Reduce noise filter 2025-01-27 16:35:59 -05:00
ColonelParrot
42f28b2bc8 Bump to v1.3.0 2025-01-27 16:01:47 -05:00
ColonelParrot
084b33ff76 Improve recognition algorithm 2025-01-27 16:00:22 -05:00
ColonelParrot
b6ba8178fc Update test.js to process all test images 2025-01-27 16:00:10 -05:00
ColonelParrot
eff1b752fe add additional test pictures (andrewdcampbell/OpenCV-Document-Scanner) 2025-01-27 15:31:24 -05:00
ColonelParrot
1670c7f7c2
Update old links 2024-12-26 02:07:02 -05:00
22 changed files with 77 additions and 60 deletions

View File

@ -1,3 +1 @@
## The repository has been moved to [puffinsoft/jscanify](https://github.com/puffinsoft/jscanify) # this repository has been moved to [puffinsoft/jscanify](https://github.com/puffinsoft/jscanify)
This is a mirror of [puffinsoft/jscanify](https://github.com/puffinsoft/jscanify). Please direct all issues, stars and forks towards that repository.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

BIN
docs/images/galaxy.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 51 KiB

BIN
docs/images/logo-github.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
docs/images/test/test10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
docs/images/test/test3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
docs/images/test/test4.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/images/test/test5.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
docs/images/test/test6.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
docs/images/test/test7.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
docs/images/test/test8.JPG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

BIN
docs/images/test/test9.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

@ -9,7 +9,7 @@ body {
#hero { #hero {
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
background-image: url("images/galaxy.png"); background-image: url("images/galaxy.webp");
background-size: cover; background-size: cover;
background-position: 0 -170px; background-position: 0 -170px;
background-attachment: fixed; background-attachment: fixed;

View File

@ -20,7 +20,7 @@
<body> <body>
<div id="hero" style="position: relative"> <div id="hero" style="position: relative">
<a href="https://github.com/ColonelParrot/jscanify" aria-label="View the library on GitHub" target="_blank" style="position: absolute; top: 0; right: 0"> <a href="https://github.com/puffinsoft/jscanify" aria-label="View the library on GitHub" target="_blank" style="position: absolute; top: 0; right: 0">
<svg width="80" height="80" viewBox="0 0 250 250" <svg width="80" height="80" viewBox="0 0 250 250"
style="fill:white; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"> style="fill:white; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
@ -32,11 +32,11 @@
fill="black" class="octo-body"></path> fill="black" class="octo-body"></path>
</svg> </svg>
</a> </a>
<img src="images/logo-full-small.png" alt="jscanify logo" /> <img src="images/logo-full.png" alt="jscanify logo" style="height: 100px" />
<h2>Open-source pure Javascript implemented mobile document scanner.</h2> <h2>the javascript document scanning library.</h2>
<br /> <br />
<div class="view-on"> <div class="view-on">
<a class="view-on-option" href="https://github.com/ColonelParrot/jscanify" target="_blank" style="margin: 10px"> <a class="view-on-option" href="https://github.com/puffinsoft/jscanify" target="_blank" style="margin: 10px">
<svg width="16" height="16" aria-hidden="true" viewBox="0 0 16 16"> <svg width="16" height="16" aria-hidden="true" viewBox="0 0 16 16">
<path fill-rule="evenodd" <path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"> d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">

View File

@ -1,17 +1,17 @@
{ {
"name": "jscanify", "name": "jscanify",
"version": "1.2.0", "version": "1.3.2",
"description": "Open-source Javascript mobile document scanner.", "description": "Open-source Javascript mobile document scanner.",
"main": "src/jscanify-node.js", "main": "src/jscanify-node.js",
"directories": { "directories": {
"doc": "docs" "doc": "docs"
}, },
"scripts": { "scripts": {
"test": "mocha" "test": "mocha --trace-uncaught"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/ColonelParrot/jscanify.git" "url": "https://github.com/puffinsoft/jscanify.git"
}, },
"keywords": [ "keywords": [
"js", "js",
@ -21,7 +21,7 @@
"author": "ColonelParrot", "author": "ColonelParrot",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/ColonelParrot/jscanify/issues" "url": "https://github.com/puffinsoft/jscanify/issues"
}, },
"homepage": "https://colonelparrot.github.io/jscanify/", "homepage": "https://colonelparrot.github.io/jscanify/",
"dependencies": { "dependencies": {

View File

@ -1,4 +1,4 @@
/*! jscanify v1.2.0 | (c) ColonelParrot and other contributors | MIT License */ /*! jscanify v1.3.2 | (c) ColonelParrot and other contributors | MIT License */
const { Canvas, createCanvas, Image, ImageData } = require("canvas"); const { Canvas, createCanvas, Image, ImageData } = require("canvas");
const { JSDOM } = require("jsdom"); const { JSDOM } = require("jsdom");
@ -44,13 +44,13 @@ class jscanify {
*/ */
findPaperContour(img) { findPaperContour(img) {
const imgGray = new cv.Mat(); const imgGray = new cv.Mat();
cv.cvtColor(img, imgGray, cv.COLOR_RGBA2GRAY); cv.Canny(img, imgGray, 50, 200);
const imgBlur = new cv.Mat(); const imgBlur = new cv.Mat();
cv.GaussianBlur( cv.GaussianBlur(
imgGray, imgGray,
imgBlur, imgBlur,
new cv.Size(5, 5), new cv.Size(3, 3),
0, 0,
0, 0,
cv.BORDER_DEFAULT cv.BORDER_DEFAULT
@ -69,6 +69,7 @@ class jscanify {
cv.RETR_CCOMP, cv.RETR_CCOMP,
cv.CHAIN_APPROX_SIMPLE cv.CHAIN_APPROX_SIMPLE
); );
let maxArea = 0; let maxArea = 0;
let maxContourIndex = -1; let maxContourIndex = -1;
for (let i = 0; i < contours.size(); ++i) { for (let i = 0; i < contours.size(); ++i) {

View File

@ -1,11 +1,11 @@
/*! jscanify v1.2.0 | (c) ColonelParrot and other contributors | MIT License */ /*! jscanify v1.3.2 | (c) ColonelParrot and other contributors | MIT License */
(function (global, factory) { (function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" typeof exports === "object" && typeof module !== "undefined"
? (module.exports = factory()) ? (module.exports = factory())
: typeof define === "function" && define.amd : typeof define === "function" && define.amd
? define(factory) ? define(factory)
: (global.jscanify = factory()); : (global.jscanify = factory());
})(this, function () { })(this, function () {
"use strict"; "use strict";
@ -20,7 +20,7 @@
} }
class jscanify { class jscanify {
constructor() {} constructor() { }
/** /**
* Finds the contour of the paper within the image * Finds the contour of the paper within the image
@ -29,13 +29,13 @@
*/ */
findPaperContour(img) { findPaperContour(img) {
const imgGray = new cv.Mat(); const imgGray = new cv.Mat();
cv.cvtColor(img, imgGray, cv.COLOR_RGBA2GRAY); cv.Canny(img, imgGray, 50, 200);
const imgBlur = new cv.Mat(); const imgBlur = new cv.Mat();
cv.GaussianBlur( cv.GaussianBlur(
imgGray, imgGray,
imgBlur, imgBlur,
new cv.Size(5, 5), new cv.Size(3, 3),
0, 0,
0, 0,
cv.BORDER_DEFAULT cv.BORDER_DEFAULT
@ -47,7 +47,7 @@
imgThresh, imgThresh,
0, 0,
255, 255,
cv.THRESH_BINARY + cv.THRESH_OTSU cv.THRESH_OTSU
); );
let contours = new cv.MatVector(); let contours = new cv.MatVector();
@ -60,6 +60,7 @@
cv.RETR_CCOMP, cv.RETR_CCOMP,
cv.CHAIN_APPROX_SIMPLE cv.CHAIN_APPROX_SIMPLE
); );
let maxArea = 0; let maxArea = 0;
let maxContourIndex = -1; let maxContourIndex = -1;
for (let i = 0; i < contours.size(); ++i) { for (let i = 0; i < contours.size(); ++i) {

View File

@ -6,71 +6,75 @@ console.log("RUNNING JSCANIFY TESTS");
console.log("Warning: This may take a bit"); console.log("Warning: This may take a bit");
const { loadImage, createCanvas } = require("canvas"); const { loadImage, createCanvas } = require("canvas");
const { mkdirSync, writeFileSync, unlinkSync, existsSync } = require("fs"); const { mkdirSync, writeFileSync, unlinkSync, existsSync, readdirSync } = require("fs");
const assert = require("assert"); const assert = require("assert");
const jscanify = require("../src/jscanify-node"); const jscanify = require("../src/jscanify-node");
const path = require("path"); const path = require("path");
const outputPaths = {
highlight: __dirname + "/output/highlighted.jpg",
extracted: __dirname + "/output/extracted.jpg",
cornerPoints: __dirname + "/output/corner_points.jpg",
};
const baseFolder = __dirname.replaceAll("\\", "/") + "/output/"; const OUTPUT_FOLDER = __dirname.replaceAll("\\", "/") + "/output/";
const TEST_IMAGE_PATH = path.join( const TEST_IMAGE_DIRECTORY = path.join(
__dirname, __dirname,
"..", "..",
"docs", "docs",
"images", "images",
"test", "test"
"test.png"
); );
/**
* delete previously generated output images
*/
function setup() { function setup() {
console.log("=== setting up tests ==="); console.log("=== setting up tests ===");
console.log("Deleting previously generated images"); console.log("Deleting previously generated images");
Object.values(outputPaths).forEach((path) => {
if (existsSync(path)) {
unlinkSync(path);
}
});
if (!existsSync(baseFolder)) { if (!existsSync(OUTPUT_FOLDER)) {
mkdirSync(baseFolder); mkdirSync(OUTPUT_FOLDER);
} }
readdirSync(OUTPUT_FOLDER).forEach((file) => {
unlinkSync(path.join(OUTPUT_FOLDER, file));
})
} }
function test() { console.log("=== beginning tests ===");
const scanner = new jscanify(); console.log("loading OpenCV.js...");
console.log("=== beginning tests ==="); const scanner = new jscanify();
console.log("loading OpenCV.js..."); scanner.loadOpenCV(function (cv) {
scanner.loadOpenCV(function (cv) {
console.log("Finished loading OpenCV.js"); console.log("Finished loading OpenCV.js");
console.log("Writing test images to: " + baseFolder); console.log("Writing test images to: " + OUTPUT_FOLDER);
describe("feature tests", function () {
/**
* tests an individual image
*/
function test(testImage, imageCount) {
describe("image #" + imageCount, function () {
it("should highlight paper", function (done) { it("should highlight paper", function (done) {
const highlighted = scanner.highlightPaper(testImage); const highlighted = scanner.highlightPaper(testImage);
const higlightedOutputPath = OUTPUT_FOLDER + "highlighted-" + imageCount + ".jpg";
writeFileSync( writeFileSync(
outputPaths.highlight, higlightedOutputPath,
highlighted.toBuffer("image/jpeg") highlighted.toBuffer("image/jpeg")
); );
assert.ok(existsSync(outputPaths.highlight)); assert.ok(existsSync(higlightedOutputPath));
done(); done();
}); });
it("should extract paper", function (done) { it("should extract paper", function (done) {
const extracted = scanner.extractPaper(testImage, 386, 500); const extracted = scanner.extractPaper(testImage, 386, 500);
const extractedOutputPath = OUTPUT_FOLDER + "extracted-" + imageCount + ".jpg";
writeFileSync( writeFileSync(
outputPaths.extracted, extractedOutputPath,
extracted.toBuffer("image/jpeg") extracted.toBuffer("image/jpeg")
); );
assert.ok(existsSync(outputPaths.extracted)); assert.ok(existsSync(extractedOutputPath));
done(); done();
}); });
@ -103,18 +107,31 @@ function test() {
ctx.fill(); ctx.fill();
}); });
writeFileSync(outputPaths.cornerPoints, canvas.toBuffer("image/jpeg")); const cornerPointsOutputPath = OUTPUT_FOLDER + "corner_points-" + imageCount + ".jpg";
writeFileSync(cornerPointsOutputPath, canvas.toBuffer("image/jpeg"));
assert.ok(existsSync(outputPaths.cornerPoints)); assert.ok(existsSync(cornerPointsOutputPath));
done(); done();
}); });
}); });
}); }
}
let testImage;
loadImage(TEST_IMAGE_PATH).then(function (image) {
testImage = image;
setup(); setup();
test();
}); let imageCount = 1;
/*
* go through all images in test image directory
*/
readdirSync(TEST_IMAGE_DIRECTORY).forEach((file) => {
const TEST_IMAGE_PATH = path.join(TEST_IMAGE_DIRECTORY, file);
if(!file.endsWith("-sized.png")){ // these images are for the website, not testing
let tempCount = imageCount++;
loadImage(TEST_IMAGE_PATH).then(function (image) {
test(image, tempCount);
});
}
})
});