Last active
May 1, 2018 08:22
-
-
Save thEpisode/9a225b659bb9eb43475c99714a91c8b1 to your computer and use it in GitHub Desktop.
Ionic v3 OCR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar> | |
<ion-title> | |
OCR Ionic 3 | |
</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content padding> | |
<span>{{recognizedText}}</span> | |
<img src="assets/img/demo.png" #demoImg class="start-api" /> | |
<img [src]="image" #imageResult /> | |
<div *ngIf="_ocrIsLoaded && !image"> | |
<img src="assets/img/Start-arrow.png" #start class="start-arrow" /> | |
</div> | |
<div *ngIf="image && showEditFilters"> | |
<ion-list> | |
<ion-list-header> | |
Adjust Image Filters | |
</ion-list-header> | |
<ion-item> | |
<ion-label>Brightness</ion-label> | |
<ion-range min="-100" max="100" pin="true" step="1" [(ngModel)]="brightness" color="secondary"> | |
<ion-icon range-left small name="sunny"></ion-icon> | |
<ion-icon range-right name="sunny"></ion-icon> | |
</ion-range> | |
</ion-item> | |
<ion-item> | |
<ion-label>Contrast</ion-label> | |
<ion-range min="-100" max="100" pin="true" step="1" [(ngModel)]="contrast" color="secondary"> | |
<ion-icon range-left small name="contrast"></ion-icon> | |
<ion-icon range-right name="contrast"></ion-icon> | |
</ion-range> | |
</ion-item> | |
<ion-item> | |
<ion-label>UnsharpMask Radius</ion-label> | |
<ion-range min="0" max="200" pin="true" step="1" [(ngModel)]="unsharpMask.radius" color="secondary"> | |
<ion-icon range-left small name="ios-radio"></ion-icon> | |
<ion-icon range-right name="ios-radio"></ion-icon> | |
</ion-range> | |
</ion-item> | |
<ion-item> | |
<ion-label>UnsharpMask Strength</ion-label> | |
<ion-range min="0" max="5" step="0.5" pin="true" [(ngModel)]="unsharpMask.strength" color="secondary"> | |
<ion-icon range-left small name="md-cog"></ion-icon> | |
<ion-icon range-right name="md-cog"></ion-icon> | |
</ion-range> | |
</ion-item> | |
<ion-item> | |
<ion-label>Hue</ion-label> | |
<ion-range min="-100" max="100" pin="true" step="1" [(ngModel)]="hue" color="secondary"> | |
<ion-icon range-left small name="md-color-palette"></ion-icon> | |
<ion-icon range-right name="md-color-palette"></ion-icon> | |
</ion-range> | |
</ion-item> | |
<ion-item> | |
<ion-label>Saturation</ion-label> | |
<ion-range min="-100" max="100" pin="true" step="1" [(ngModel)]="saturation" color="secondary"> | |
<ion-icon range-left small name="thermometer"></ion-icon> | |
<ion-icon range-right name="thermometer"></ion-icon> | |
</ion-range> | |
</ion-item> | |
</ion-list> | |
</div> | |
<ion-fab right bottom> | |
<button ion-fab (click)="openMenu()" color="danger"><ion-icon name="add"></ion-icon></button> | |
</ion-fab> | |
</ion-content> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, ViewChild, ElementRef, NgZone } from '@angular/core'; | |
import { NavController } from 'ionic-angular'; | |
import { Camera } from '@ionic-native/camera'; | |
import { Platform, ActionSheetController, LoadingController } from 'ionic-angular'; | |
import Tesseract from 'tesseract.js'; | |
@Component({ | |
selector: 'page-home', | |
templateUrl: 'home.html' | |
}) | |
export class HomePage { | |
@ViewChild('imageResult') private imageResult: ElementRef; | |
@ViewChild('demoImg') private demoImg: ElementRef; | |
private recognizedText: string; | |
image: string = ''; | |
_zone: any; | |
_ocrIsLoaded: boolean = false; | |
brightness: number = 12; | |
contrast: number = 52; | |
unsharpMask: any = { radius: 100, strength: 2 }; | |
hue: number = -100; | |
saturation: number = -100; | |
showEditFilters: boolean = false; | |
constructor( | |
private camera: Camera, | |
public navCtrl: NavController, | |
public platform: Platform, | |
public loadingCtrl: LoadingController, | |
public actionsheetCtrl: ActionSheetController) { | |
this._zone = new NgZone({ enableLongStackTrace: false }); | |
} | |
openMenu() { | |
if (this._ocrIsLoaded === true) { | |
let actionSheet; | |
if (!this.image) { | |
actionSheet = this.actionsheetCtrl.create({ | |
title: 'Actions', | |
cssClass: 'action-sheets-basic-page', | |
buttons: [ | |
{ | |
text: 'Random demo', | |
icon: !this.platform.is('ios') ? 'shuffle' : null, | |
handler: () => { | |
this.randomDemo() | |
} | |
}, | |
{ | |
text: 'Take Photo', | |
icon: !this.platform.is('ios') ? 'camera' : null, | |
handler: () => { | |
this.takePicture() | |
} | |
}, | |
{ | |
text: 'Cancel', | |
role: 'cancel', // will always sort to be on the bottom | |
icon: !this.platform.is('ios') ? 'close' : null, | |
handler: () => { | |
console.log('Cancel clicked'); | |
} | |
} | |
] | |
}); | |
} | |
else { | |
actionSheet = this.actionsheetCtrl.create({ | |
title: 'Actions', | |
cssClass: 'action-sheets-basic-page', | |
buttons: [ | |
{ | |
text: 'Random demo', | |
icon: !this.platform.is('ios') ? 'shuffle' : null, | |
handler: () => { | |
this.randomDemo() | |
} | |
}, | |
{ | |
text: 'Re-Take photo', | |
icon: !this.platform.is('ios') ? 'camera' : null, | |
handler: () => { | |
this.takePicture() | |
} | |
}, | |
{ | |
text: 'Apply filters', | |
icon: !this.platform.is('ios') ? 'barcode' : null, | |
handler: () => { | |
this.filter() | |
} | |
}, | |
{ | |
text: 'Clean filters', | |
icon: !this.platform.is('ios') ? 'refresh' : null, | |
handler: () => { | |
this.restoreImage() | |
} | |
}, | |
{ | |
text: this.showEditFilters == false ? 'Customize filters' : 'Hide customization filters', | |
icon: !this.platform.is('ios') ? 'hammer' : null, | |
handler: () => { | |
this.showEditFilters = this.showEditFilters == false ? true : false; | |
} | |
}, | |
{ | |
text: 'Read image', | |
icon: !this.platform.is('ios') ? 'analytics' : null, | |
handler: () => { | |
this.analyze(this.imageResult.nativeElement.src, false); | |
} | |
}, | |
{ | |
text: 'Cancel', | |
role: 'cancel', // will always sort to be on the bottom | |
icon: !this.platform.is('ios') ? 'close' : null, | |
handler: () => { | |
console.log('Cancel clicked'); | |
} | |
} | |
] | |
}); | |
} | |
actionSheet.present(); | |
} | |
else { | |
alert('OCR API is not loaded'); | |
} | |
} | |
restoreImage() { | |
if (this.image) { | |
this.imageResult.nativeElement.src = this.image; | |
} | |
} | |
takePicture() { | |
let loader = this.loadingCtrl.create({ | |
content: 'Please wait...' | |
}); | |
loader.present(); | |
// Take a picture saving in device, as jpg and allows edit | |
this.camera.getPicture({ | |
quality: 100, | |
destinationType: this.camera.DestinationType.NATIVE_URI, | |
encodingType: this.camera.EncodingType.JPEG, | |
targetHeight: 1000, | |
sourceType: 1, | |
allowEdit: true, | |
saveToPhotoAlbum: true, | |
correctOrientation: true | |
}).then((imageURI) => { | |
loader.dismissAll(); | |
this.image = imageURI; | |
}, (err) => { | |
console.log(`ERROR -> ${JSON.stringify(err)}`); | |
}); | |
} | |
filter() { | |
/// Initialization of glfx.js | |
/// is important, to use js memory elements | |
/// access to Window element through (<any>window) | |
try { | |
var canvas = (<any>window).fx.canvas(); | |
} catch (e) { | |
alert(e); | |
return; | |
} | |
/// taken from glfx documentation | |
var imageElem = this.imageResult.nativeElement; // another trick is acces to DOM element | |
var texture = canvas.texture(imageElem); | |
canvas.draw(texture) | |
.hueSaturation(this.hue / 100, this.saturation / 100)//grayscale | |
.unsharpMask(this.unsharpMask.radius, this.unsharpMask.strength) | |
.brightnessContrast(this.brightness / 100, this.contrast / 100) | |
.update(); | |
/// replace image src | |
imageElem.src = canvas.toDataURL('image/png'); | |
} | |
analyze(image, loadAPI) { | |
let loader = this.loadingCtrl.create({ | |
content: 'Please wait...' | |
}); | |
loader.present(); | |
if (loadAPI == true) { | |
this._ocrIsLoaded = false; | |
} | |
/// Recognize data from image | |
Tesseract.recognize(image, {}) | |
.progress((progress) => { | |
this._zone.run(() => { | |
loader.setContent(`${progress.status}: ${Math.floor(progress.progress * 100)}%`) | |
console.log('progress:', progress); | |
}) | |
}) | |
.then((tesseractResult) => { | |
this._zone.run(() => { | |
loader.dismissAll(); | |
if (loadAPI == true) { | |
this._ocrIsLoaded = true; | |
} | |
console.log('Tesseract result: '); | |
console.log(tesseractResult); | |
/// Show a result if data isn't initializtion | |
if (loadAPI != true) { this.recognizedText = tesseractResult.text; } | |
}); | |
}); | |
} | |
randomDemo(){ | |
} | |
ionViewDidLoad() { | |
console.log('loaded') | |
this.analyze(this.demoImg.nativeElement.src, true); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You need to image as well