Initial commit
This commit is contained in:
+59
@@ -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>
|
||||
Binary file not shown.
|
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,
|
||||
};
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user