Cleaned up and improved OCR operation

This commit is contained in:
n1474335 2019-09-13 14:34:08 +01:00
parent a8ad10757c
commit 7eabaf0de6
3 changed files with 48 additions and 28 deletions

View file

@ -383,6 +383,7 @@
"ops": [ "ops": [
"Render Image", "Render Image",
"Play Media", "Play Media",
"Optical Character Recognition",
"Remove EXIF", "Remove EXIF",
"Extract EXIF", "Extract EXIF",
"Split Colour Channels", "Split Colour Channels",
@ -405,8 +406,7 @@
"Hex Density chart", "Hex Density chart",
"Scatter chart", "Scatter chart",
"Series chart", "Series chart",
"Heatmap chart", "Heatmap chart"
"OCR"
] ]
}, },
{ {

View file

@ -1,4 +1,5 @@
/** /**
* @author n1474335 [n1474335@gmail.com]
* @author mshwed [m@ttshwed.com] * @author mshwed [m@ttshwed.com]
* @copyright Crown Copyright 2019 * @copyright Crown Copyright 2019
* @license Apache-2.0 * @license Apache-2.0
@ -7,30 +8,36 @@
import Operation from "../Operation.mjs"; import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs"; import OperationError from "../errors/OperationError.mjs";
import { isImage } from "../lib/FileType.mjs"; import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs"; import { isWorkerEnvironment } from "../Utils.mjs";
import jimp from "jimp";
import Tesseract from "tesseract.js"; import Tesseract from "tesseract.js";
const { TesseractWorker } = Tesseract; const { TesseractWorker } = Tesseract;
/** /**
* OCR operation * Optical Character Recognition operation
*/ */
class OCR extends Operation { class OpticalCharacterRecognition extends Operation {
/** /**
* OCR constructor * OpticalCharacterRecognition constructor
*/ */
constructor() { constructor() {
super(); super();
this.name = "OCR"; this.name = "Optical Character Recognition";
this.module = "Default"; this.module = "Image";
this.description = "Optical character recognition or optical character reader (OCR) is the mechanical or electronic conversion of images of typed, handwritten or printed text into machine-encoded text."; this.description = "Optical character recognition or optical character reader (OCR) is the mechanical or electronic conversion of images of typed, handwritten or printed text into machine-encoded text.<br><br>Supported image formats: png, jpg, bmp, pbm.";
this.infoURL = "https://en.wikipedia.org/wiki/Optical_character_recognition"; this.infoURL = "https://wikipedia.org/wiki/Optical_character_recognition";
this.inputType = "ArrayBuffer"; this.inputType = "ArrayBuffer";
this.outputType = "string"; this.outputType = "string";
this.args = []; this.args = [
{
name: "Show confidence",
type: "boolean",
value: true
}
];
} }
/** /**
@ -39,34 +46,32 @@ class OCR extends Operation {
* @returns {string} * @returns {string}
*/ */
async run(input, args) { async run(input, args) {
if (!isImage(input)) { const [showConfidence] = args;
const type = isImage(input);
if (!type) {
throw new OperationError("Invalid File Type"); throw new OperationError("Invalid File Type");
} }
try { try {
if (isWorkerEnvironment()) const image = `data:${type};base64,${toBase64(input)}`;
self.sendStatusMessage("Performing OCR on image...");
let image;
try {
image = await jimp.read(input);
image = await image.getBase64Async(jimp.AUTO);
} catch (err) {
throw new OperationError(`Error loading image. (${err})`);
}
const worker = new TesseractWorker(); const worker = new TesseractWorker();
const result = await worker.recognize(image) const result = await worker.recognize(image)
.progress(progress => { .progress(progress => {
if (isWorkerEnvironment()) self.sendStatusMessage(`${progress.status} - ${(parseFloat(progress.progress)*100).toFixed(2)}%`); if (isWorkerEnvironment()) {
self.sendStatusMessage(`Status: ${progress.status} - ${(parseFloat(progress.progress)*100).toFixed(2)}%`);
}
}); });
if (showConfidence) {
return `Confidence: ${result.confidence}%\n\n${result.text}`;
} else {
return result.text; return result.text;
}
} catch (err) { } catch (err) {
throw new OperationError(`Error performing OCR on image. (${err})`); throw new OperationError(`Error performing OCR on image. (${err})`);
} }
} }
} }
export default OCR; export default OpticalCharacterRecognition;

View file

@ -247,5 +247,20 @@ TestRegister.addTests([
args: ["None"] args: ["None"]
} }
] ]
},
/*{ Commented out as it takes a while to run and drops a file to disk (eng.traineddata)
name: "Optical Character Recognition",
input: "iVBORw0KGgoAAAANSUhEUgAAAUAAAAC0CAIAAABqhmJGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAASuSURBVHhe7dftVdswAIbRzsVAzMM0XabDUCOUxLYsWW4Jp+/pvf9w9GH76CHw4x2IJWAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAI9p8G/PbyY8rL2686g8t+vnqHTyfgIYfvz/26veTXn/UKX8+f0EU9bHrtu/6KfAN/AwEXAj7lFf2TBFw4nae8on+SgIvJ01n/KLzpDK+L3bT/Ap4O+HC+V12mTH+M3gzcLbIY/EO6HfxYp13k09nb6r3UqcdnjoCL3ll72J26h+35Oxy2XvZ0wOLaXq9v2+F1UC+7RZtMZ/DnfX1lwDOPzwUCLo7O2trtDK8H3M/iqoc6bj1subT68XTA/F7bGJooyzKbhTvLPHY8eJLHlbNX1DqYUVfdXbqwJjsCLsans37aNNJM6w68OR0wv9f9ymKw3k67yn2ZZpHlg3a3zis60s6oV+ZvlzMCLoanc3Dsdt9TdWT/lM8OmNjr5KY72jmzq1zfrbvXtVtmRMDF8HTWcgaaqIrD1U4G/MFewxrW262s5jS/Fzpmdts6mnHy+Fwl4GJ0OjsNrG1P/y7CNo3+gEt7jW56MVprNed7A/5w+n6YJ+BieDpnj/jO6pweTz0acGWvmZveL9XOmd3x6wKuTt8PEwRczLRw4eje1XX7c/cDruw1uuneOu2c4aOvzI57mJhRh1xZlQ0BF+Oz9vcF96fuB1zYa7R2b5mD6/XSwdfg8snj4q21+W/L02dfzIxhQMDFyTm6Hd7m+JYP7rPKT5sRuzhOBywm91rUkYc3fV9ltchtr8VmzuGOdfDB9N1tFYefNfdXLmyGjNZkhoCLUQufVqd/7z7rUcLW/XieDvg0s9difNOdRV5ePibt5vTuazusWbF9rs2E5v4mH58LBFyMW7g5OID7s9cMuTygmt9rcNPb5MrAz0lHc3Z9Ht7XZsxqxO36ZtLR/c0+PpMEzLOc/4LhrwmYZ6lfywJ+JgHzJPr9DgLmi23/zdXvcwmYL7YKWL1PJ2AIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmAIJmCI9f7+G6yFxVg/GyYwAAAAAElFTkSuQmCC",
expectedOutput: "Tesseract.js\n",
recipeConfig: [
{
"op": "From Base64",
"args": ["A-Za-z0-9+/=", true]
},
{
"op": "Optical Character Recognition",
"args": [false]
} }
]
}*/
]); ]);