commit
19743356f1
10 changed files with 3627 additions and 0 deletions
@ -0,0 +1,59 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
|
|||
# Runtime data |
|||
pids |
|||
*.pid |
|||
*.seed |
|||
|
|||
# Directory for instrumented libs generated by jscoverage/JSCover |
|||
lib-cov |
|||
|
|||
# Coverage directory used by tools like istanbul |
|||
coverage |
|||
|
|||
# nyc test coverage |
|||
.nyc_output |
|||
|
|||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
|||
.grunt |
|||
|
|||
# node-waf configuration |
|||
.lock-wscript |
|||
|
|||
# Compiled binary addons (http://nodejs.org/api/addons.html) |
|||
build/Release |
|||
|
|||
# Dependency directories |
|||
node_modules |
|||
jspm_packages |
|||
|
|||
# Optional npm cache directory |
|||
.npm |
|||
|
|||
# Optional REPL history |
|||
.node_repl_history |
|||
|
|||
# 0x |
|||
profile-* |
|||
|
|||
# mac files |
|||
.DS_Store |
|||
|
|||
# vim swap files |
|||
*.swp |
|||
|
|||
# webstorm |
|||
.idea |
|||
|
|||
# vscode |
|||
.vscode |
|||
*code-workspace |
|||
|
|||
# clinic |
|||
profile* |
|||
*clinic* |
|||
*flamegraph* |
|||
.bash_history |
@ -0,0 +1,24 @@ |
|||
'use strict' |
|||
|
|||
const path = require('path') |
|||
const AutoLoad = require('fastify-autoload') |
|||
|
|||
|
|||
module.exports = async function (fastify, opts) { |
|||
|
|||
fastify.register(require('fastify-static'), { |
|||
root: path.join(__dirname, 'public'), |
|||
prefix: '/', // optional: default '/'
|
|||
}) |
|||
// Place here your custom code!
|
|||
|
|||
// Do not touch the following lines
|
|||
|
|||
|
|||
// This loads all plugins defined in routes
|
|||
// define your routes in one of these
|
|||
fastify.register(AutoLoad, { |
|||
dir: path.join(__dirname, 'routes'), |
|||
options: Object.assign({}, opts) |
|||
}) |
|||
} |
@ -0,0 +1,30 @@ |
|||
{ |
|||
"name": "ocrapp", |
|||
"version": "1.0.0", |
|||
"description": "", |
|||
"main": "app.js", |
|||
"directories": { |
|||
"test": "test" |
|||
}, |
|||
"scripts": { |
|||
"test": "tap \"test/**/*.test.js\"", |
|||
"start": "fastify start -l info app.js", |
|||
"dev": "fastify start -w -l info -P app.js" |
|||
}, |
|||
"keywords": [], |
|||
"author": "", |
|||
"license": "ISC", |
|||
"dependencies": { |
|||
"fastify": "^3.0.0", |
|||
"fastify-autoload": "^3.3.1", |
|||
"fastify-cli": "^2.13.0", |
|||
"fastify-multipart": "^5.0.0", |
|||
"fastify-plugin": "^3.0.0", |
|||
"fastify-sensible": "^3.1.0", |
|||
"fastify-static": "^4.2.3", |
|||
"mime-types": "^2.1.32" |
|||
}, |
|||
"devDependencies": { |
|||
"tap": "^15.0.9" |
|||
} |
|||
} |
@ -0,0 +1,90 @@ |
|||
/* |
|||
* ഓം ബ്രഹ്മാർപ്പണം |
|||
* app.js |
|||
* Created: Mon Mar 09 2020 02:16:15 GMT+0530 (GMT+05:30) |
|||
* Copyright 2020 Harish.K<harish2704@gmail.com> |
|||
*/ |
|||
|
|||
function ocrByServer(image) { |
|||
var data = new FormData(); |
|||
data.append("image", image); |
|||
return fetch( |
|||
"/ocr", |
|||
{ |
|||
method: "POST", |
|||
body: data, |
|||
} |
|||
).then((res) => res.json()); |
|||
} |
|||
|
|||
|
|||
new Vue({ |
|||
el: "#main", |
|||
components: { |
|||
}, |
|||
data: { |
|||
scalingFactor: 1, |
|||
selectedFileName: "", |
|||
currentFileBlob: null, |
|||
isLoading: false, |
|||
ocrOutput: "", |
|||
}, |
|||
methods: { |
|||
doOcr: function () { |
|||
this.isLoading = true; |
|||
ocrByServer(this.currentFileBlob) |
|||
.then((data) => { |
|||
console.log("success", data); |
|||
this.ocrOutput = data.text; |
|||
this.isLoading = false; |
|||
}) |
|||
.catch((error) => { |
|||
console.log("error", error); |
|||
alert("Some error occurred while Calling OCR API"); |
|||
this.isLoading = false; |
|||
}); |
|||
}, |
|||
|
|||
setImage: function (file) { |
|||
var self = this; |
|||
var canvas = this.$refs.canvas; |
|||
var ctx = canvas.getContext("2d"); |
|||
var img = new Image(); |
|||
this.currentFileBlob = file; |
|||
img.onload = function () { |
|||
canvas.width = img.width; |
|||
canvas.height = img.height; |
|||
ctx.drawImage(img, 0, 0); |
|||
self.scalingFactor = canvas.clientWidth / canvas.width; |
|||
}; |
|||
img.src = URL.createObjectURL(file); |
|||
}, |
|||
|
|||
onChangeFile: function File(e) { |
|||
this.setImage(e.target.files[0]); |
|||
this.selectedFileName = e.target.files[0].name; |
|||
}, |
|||
}, |
|||
mounted: function () { |
|||
var self = this; |
|||
fetch("./sample.png") |
|||
.then((v) => v.blob()) |
|||
.then((blob) => this.setImage(blob)); |
|||
document.onpaste = function (event) { |
|||
var items = (event.clipboardData || event.originalEvent.clipboardData) |
|||
.items; |
|||
for (var index in items) { |
|||
var item = items[index]; |
|||
if (item.kind === "file") { |
|||
var blob = item.getAsFile(); |
|||
self.setImage(blob); |
|||
self.ocrOutput = ""; |
|||
} |
|||
} |
|||
}; |
|||
window.addEventListener("resize", function () { |
|||
var canvas = self.$refs.canvas; |
|||
self.scalingFactor = canvas.clientWidth / canvas.width; |
|||
}); |
|||
}, |
|||
}); |
@ -0,0 +1,114 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<title>Tesseract OCR Malayalam demo</title> |
|||
<link |
|||
rel="stylesheet" |
|||
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" |
|||
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" |
|||
crossorigin="anonymous" |
|||
/> |
|||
<style type="text/css" media="all"> |
|||
.btn .spinner-border, |
|||
.btn .txt-loading, |
|||
.btn[disabled] .txt-button { |
|||
display: none; |
|||
} |
|||
.btn[disabled] .spinner-border, |
|||
.btn[disabled] .txt-loading, |
|||
.btn .txt-button { |
|||
display: inline-block; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div class="container-fluid" id="main"> |
|||
<div class="row"> |
|||
<div class="col-md-12"> |
|||
<h2>Tesseract OCR Malayalam</h2> |
|||
<h4 class="text-danger">Please note</h4> |
|||
<ol> |
|||
<li>It can detect both Malayalam & English script</li> |
|||
<li>Pasting image from clip board is supported</li> |
|||
</ol> |
|||
</div> |
|||
|
|||
<div class="col-md-12"> |
|||
<div class="col-md-6 col-sm-12"> |
|||
<div class="form-group"> |
|||
<input |
|||
type="file" |
|||
accept="image/*" |
|||
style="visibility: hidden; height: 0" |
|||
@change="onChangeFile($event)" |
|||
ref="file_input" |
|||
/> |
|||
<div class="input-group input-file"> |
|||
<input |
|||
type="text" |
|||
readonly |
|||
v-model="selectedFileName" |
|||
class="form-control" |
|||
placeholder="Choose a file..." |
|||
@click="$refs.file_input.click()" |
|||
/> |
|||
<div class="input-group-append"> |
|||
<button |
|||
class="btn btn-primary btn-choose" |
|||
type="button" |
|||
@click="$refs.file_input.click()" |
|||
> |
|||
Choose another image |
|||
</button> |
|||
<button |
|||
class="btn btn-success pull-right" |
|||
@click="doOcr()" |
|||
:disabled="isLoading" |
|||
> |
|||
<span |
|||
class="spinner-border spinner-border-sm" |
|||
role="status" |
|||
aria-hidden="true" |
|||
></span> |
|||
<span class="txt-loading">Loading...</span> |
|||
<span class="txt-button">Run OCR</span> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row w-100"> |
|||
<div class="col-md-6 col-sm-12"> |
|||
<div> |
|||
<canvas |
|||
ref="canvas" |
|||
class="w-100" |
|||
alt="Selected image" |
|||
@resize="onCanvasResize($event)" |
|||
></canvas> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 col-sm-12"> |
|||
<div class="card"> |
|||
<div class="card-body"> |
|||
<h5 class="card-title text-primary">OCR Output</h5> |
|||
<div id="output"> |
|||
<textarea |
|||
class="form-control" |
|||
rows="15" |
|||
v-model="ocrOutput" |
|||
></textarea> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> |
|||
<script src="./app.js" type="text/javascript" charset="utf-8"></script> |
|||
</body> |
|||
</html> |
After Width: | Height: | Size: 108 KiB |
@ -0,0 +1,27 @@ |
|||
# Routes Folder |
|||
|
|||
Routes define routes within your application. Fastify provides an |
|||
easy path to a microservice architecture, in the future you might want |
|||
to independently deploy some of those. |
|||
|
|||
In this folder you should define all the routes that define the endpoints |
|||
of your web application. |
|||
Each service is a [Fastify |
|||
plugin](https://www.fastify.io/docs/latest/Plugins/), it is |
|||
encapsulated (it can have its own independent plugins) and it is |
|||
typically stored in a file; be careful to group your routes logically, |
|||
e.g. all `/users` routes in a `users.js` file. We have added |
|||
a `root.js` file for you with a '/' root added. |
|||
|
|||
If a single file become too large, create a folder and add a `index.js` file there: |
|||
this file must be a Fastify plugin, and it will be loaded automatically |
|||
by the application. You can now add as many files as you want inside that folder. |
|||
In this way you can create complex routes within a single monolith, |
|||
and eventually extract them. |
|||
|
|||
If you need to share functionality between routes, place that |
|||
functionality into the `plugins` folder, and share it via |
|||
[decorators](https://www.fastify.io/docs/latest/Decorators/). |
|||
|
|||
If you're a bit confused about using `async/await` to write routes, you would |
|||
better take a look at [Promise resolution](https://www.fastify.io/docs/latest/Routes/#promise-resolution) for more details. |
@ -0,0 +1,30 @@ |
|||
"use strict"; |
|||
|
|||
const fs = require("fs"); |
|||
const util = require("util"); |
|||
const path = require("path"); |
|||
const { pipeline } = require("stream"); |
|||
const pump = util.promisify(pipeline); |
|||
const crypto = require("crypto"); |
|||
const mime = require("mime-types"); |
|||
const exec = util.promisify(require("child_process").execFile); |
|||
|
|||
const UPLOAD_PATH = "./uploads"; |
|||
|
|||
module.exports = async function (fastify, opts) { |
|||
fastify.register(require("fastify-multipart")); |
|||
fastify.post("/ocr", async function (req, reply) { |
|||
const data = await req.file(); |
|||
const uid = crypto.randomBytes(16).toString("hex"); |
|||
const filename = `${UPLOAD_PATH}/${uid}.${mime.extension(data.mimetype)}`; |
|||
const lang = "mal+eng"; |
|||
await pump(data.file, fs.createWriteStream(filename)); |
|||
const args = [filename, "stdout", "-l", lang]; |
|||
const { stdout, stderr } = await exec("tesseract", args); |
|||
exec("rm", ["-f", filename]); |
|||
return { |
|||
text: stdout, |
|||
error: stderr, |
|||
}; |
|||
}); |
|||
}; |
@ -0,0 +1 @@ |
|||
../uploads |
File diff suppressed because it is too large
Loading…
Reference in new issue