tm-ocr-photo
TypeScript icon, indicating that this package has built-in type declarations

1.4.8 • Public • Published

OcrPhoto by TalentoMOBILE

Document scanning component for Angular. Scan different types of ID documentation to obtain the following outputs:

  • Fake documentation validation
  • Data extraction
  • Photo capture

To contact TalentoMobile: soporte@talentomobile.com

INSTALATION


npm install ocr-photo-V2

COMPONENT INPUTS


INPUT
[env] Setting the environment. dev, pre, pro as parameters.
[token] Validation token.
[docType] Type of document to be analyze.

COMPONENT OUTPUTS


INPUT
(photoTaken) Receive the auto photo taken
(photoMessage) Receive the message to guide the user fot the automatic photo taken
(error) Receive any possible error.

MESSAGE TYPES

SHOW_DOCUMENT HOLD_DOCUMENT CENTER_DOCUMENT BRING_DOCUMENT_CLOSER

ERROR TYPES

DEVICES_NOT_FOUND_ERROR TRACK_START_ERROR CONSTRAINT_NOT_SATISFIED_ERROR PERMISSION_DENIED_ERROR TYPE_ERROR GENERIC_ERROR

METHODS ACCESSIBLE FROM TS


OUTPUT input output
takeframe() Capture Photo manually Blob image
sendFront() Send the front capture to be analyze. Blob image FRONT_RESPONSE
sendBackPhoto() Send the back capture to be analyze. Blob image BACK_RESPONSE
stopVideo() Close the camera ones the whole capture have finished
reset() Refresh teh photo taken to take a new photo
compressImg() Compress the image file Blob image Blob image

FRONT_RESPONSE

This response will be optimize and resented in the Back response as a global response for the whole process

  {
    "data":{
      "country": {
        "value": "string", "confidence": 0
        },
      "date_of_birth": {
        "value": "string", "confidence": 0
        },
      "doc_expire_date": {
        "value": "string", "confidence": 0
        },
      "doc_number": {
        "value": "string", "confidence": 0
        },
      "doc_type": {
        "value": "string", "confidence": 0
        },
      "name": {
        "value": "string", "confidence": 0
        },
      "nationality":{
        "value": "string", "confidence": 0
        },
      "opt_cli": {
        "value": "string", "confidence": 0
        },
      "opt_laser_grab": {
        "value": "string", "confidence": 0
        },
      "opt_number_can": {
        "value": "string", "confidence": 0
        },
      "opt_support_number": {
        "value": "string", "confidence": 0
        },
      "sex": {
        "value": "string", "confidence": 0
        },
      "surname1": {
        "value": "string", "confidence": 0
        },
      "surname2": {
        "value": "string", "confidence": 0
        }
    },
    "docType": "string",
    "frontVal":{
      "document_aspect_ratio": "boolean",
      "document_aspect_ratio_value": "number",
      "document_backwhite_check": "boolean",
      "document_typography": "boolean"
    },
    "uuid": "string"
  }

BACK_RESPONSE

{ 
  "result":
    {
        "doc_type": {
          "value": "string",
          "confidence": 0
        },
        "doc_number": {
          "value": "string",
          "confidence": 0
        },
        "personal_number": {
          "value": "string",
          "confidence": 0
        },
        "doc_expire_date": {
          "value": "string",
          "confidence": 0
        },
        "issue_date": {
          "value": "string",
          "confidence": 0
        },
        "surname1": {
          "value": "string",
          "confidence": 0
        },
        "surname2": {
          "value": "string",
          "confidence": 0
        },
        "name": {
          "value": "string",
          "confidence": 0
        },
        "sex": {
          "value": "string",
          "confidence": 0
        },
        "date_of_birth": {
          "value": "string",
          "confidence": 0
        },
        "nationality": {
          "value": "string",
          "confidence": 0
        },
        "nationality_code": {
          "value": "string",
          "confidence": 0
        },
        "country_expedition": {
          "value": "string",
          "confidence": 0
        },
        "country": {
          "value": "string",
          "confidence": 0
        },
        "address": {
          "value": "string",
          "confidence": 0
        },
        "mrz": {
          "value": "string",
          "confidence": 0
        },
        "mrz_data": {
          "doc_type": "string",
          "serial_number": "string",
          "nation_code": "string",
          "reserve_number": "string",
          "date_of_birth": "string",
          "doc_expire_date": "string",
          "sex": "string",
          "nationality_code": "string",
          "name": "string",
          "surname1": "string",
          "surname2": "string",
          "checkdigits": {}
        },
        "validationChecks": { 
          "sidesMatch": "boolean",     // ambos lados pertenecen al mismo documento
          "validMRZ": "boolean",     // Validación algorítmica del mrz
          "expired": "boolean",     // valida si los documentos están vencidos
          "legalAge": "boolean",     // valida si el titular del documento es mayor de edad por ley
          "quality": "boolean",     // valida que los campos hayan sido capturados. 3 campos vacios o mas  y la fallta del doc_number y mrz deverán un false.
          "front":{
            "face_photo": "boolean", // Verifica que hay foto de la cara en el documento
            "document_aspect_ratio" : "boolena", // Verifica la proporción de las mediciones (alt x anch)
            "document_aspect_ratio_value": "number", // Valor de las proporciones (alt x anch)
            "document_backwhite_check": "boolean" // Verifica que el documento esta en blanco y negro
          },
          "back":{
            "char_distance" : "boolean", // Verifica la distancia entre caracteres
            "char_distance_value" : "number", // Valor de distancia entre caracteres
            "document_aspect_ratio": "boolean", // Verifica la proporción de las mediciones (alt x anch)
            "document_aspect_ratio_value": "number", // Valor de las proporciones (alt x anch)
            "document_backwhite_check": "boolean", // Verifica que el documento esta en blanco y negro
            "mrz_aspect_ratio": "boolean", // Verifica la proporción de las mediciones (alt x anch) del mrz
            "mrz_aspect_ratio_value": "number", // Valor de las proporciones (alt x anch) del mrz
            "mrz_characters_count_value": "number", // Cantidad de caracteres encontrados en el mrz
            "mrz_typography": "number" // Porcentaje de valided en similitud con la fuente ocrb
          }
        },
        "opt_data": {},
        "global_confidence": "boolean" // Media de todos los confidence obtenidos
    }
  },
  "error":{
    "code": "string",
    "message": "string"
  }
}

USAGE EXAMPLE


app.module.ts (Import in your app module)

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
 
import {AppComponent} from './app.component';
import {OcrPhotoModule} from 'ocr-photo';
 
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [OcrPhotoModule],
  bootstrap: [AppComponent]
})
export class AppModule {}

app.component.ts

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { CaptureFrameService } from 'ocr-photo';

enum MessageType {
  SHOW_DOCUMENT = 'Muestra tu documento de identidad',
  HOLD_DOCUMENT = 'No muevas el documento',
  CENTER_DOCUMENT = 'Centra el documento entre los márgenes',
  BRING_DOCUMENT_CLOSER = 'Acerca el documento ajustándolo a los márgenes'
}

enum ErrorOcr {
  DEVICES_NOT_FOUND_ERROR = '',
  TRACK_START_ERROR = '',
  CONSTRAINT_NOT_SATISFIED_ERROR = '',
  PERMISSION_DENIED_ERROR = '',
  TYPE_ERROR = '',
  GENERIC_ERROR = '',
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  public imageTaken: string;
  public imageToShow
  public processID : string;
  public frontFinish = false;
  public loading = false;
  public error = false; // Show error 

  public photoMessage = '';

  constructor(
    private captureFrameService:CaptureFrameService,
    private cdRef:ChangeDetectorRef,
    private sanitizer: DomSanitizer){}

  ngOnInit() {
    return null;
  }

  // TAKE A PHOTO MANUALY AND RETRIVE THE CAPTURE IN BASE64. (we save the photo in a variable )
  async flashFoto(){
    this.imageTaken = await this.captureFrameService.takeFrame() as any
    let objectURL = URL.createObjectURL(this.imageTaken);
    this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);
    console.log(this.imageTaken);
  }

  // SENDING THE PHOTO (FRONT) TO BE ANALYSE. The response can be the end response in case is a ONE-SIDE-DOCUMENT otherwise we will capture the uuid to continue with
  sendFrontPhoto(){
    this.loading = true;
    this.cdRef.detectChanges();
    this.captureFrameService.sendFront(this.imageTaken).then((res:any) => {
      console.log(res);
      if (res.uuid) this.processID = res.uuid
      this.frontFinish = true;
      this.imageTaken = '';
      this.loading = false;
      this.error = false;
      this.cdRef.detectChanges();
    }).catch((err)=>{
      this.loading = false;
      this.error = err;
      this.imageTaken = '';
      this.cdRef.detectChanges();
      console.warn(err)
    })
  }

  // SENDING THE PHOTO (BACK) TO BE ANALYSE. OBTAINING THE END RESPONSE WITH THE RESULTS
  sendBackPhoto(){
    this.loading = true;
    this.cdRef.detectChanges();
    this.captureFrameService.sendBack(this.imageTaken, this.processID).then((res) => {
      console.log(res);
      this.loading = false;
      this.error = false;
      this.cdRef.detectChanges();
    }).catch((err)=> {
      this.loading = false;
      this.error = err;
      this.imageTaken = '';
      this.cdRef.detectChanges();
      console.warn(err)
    })
  }

  // CAPTURE THE PHOTO FROM EVENT
  photoTaken(event){
    console.log('CAPTURING PHOTO', event);
    this.imageTaken = event;
    let objectURL = URL.createObjectURL(this.imageTaken);
    this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);
    this.cdRef.detectChanges();
  }


  handleError(error){
    console.log('ERROR');
    console.log(error);
  }

  //CAPTURE THE MESSAGE FROM EVENT
  public changeMessage(event){
    this.photoMessage = MessageType[event];;
    this.cdRef.detectChanges();
  }

    // IMAGE RESIDE BLOB OUTPUT
  async onChangeFile(event){
    const file = event.target.files[0];

    const newBlobImg = await new Promise((resolve, reject) => {
      let reader = new FileReader();
      reader.onload = async (e:any) => {
         let blob = new Blob([new Uint8Array(e.target.result)], {type: file.type });
         const newBlob = await this.captureFrameService.compressImg(blob)
         resolve(newBlob)
      };
      reader.readAsArrayBuffer(file);
    })
    console.log(newBlobImg);
  }


}

app.component.html

<div class="main_container">
  <div>{{frontFinish ? 'Mostrar trasera' : 'Mostrar delantera'}}</div>

  <div class="video_box">
    <!-- // FOR THE COMPONENT TO WORK ALL THE THREE PARAMETERS MUST BE PASSED CORRECTLY -->
    <tm-ocr-photo
      #taken
      [env]="'local'"
      (photoTaken)="photoTaken($event)"
      (photoMessage)="changeMessage($event)"
      [token]="'c23...'"
      (error)="handleError($event)"
      [docType]="'ESP_DNI3'">
    </tm-ocr-photo>
  </div>

  <div>{{photoMessage}}</div>

  <button (click)="flashFoto()" style="margin-bottom:20px">Capturar imagen</button>

  <div *ngIf="imageTaken" class="photoShow">
    <img [src]="imageToShow" alt="">
    <button *ngIf="!frontFinish" (click)="taken.reset(); sendFrontPhoto()">Confirmar Front</button>
    <button *ngIf="frontFinish" (click)="sendBackPhoto()">Confirmar Back</button>
  </div>
  <div>{{error ? 'Calidad insuficiente' + error : ''}}</div>
</div>

<div *ngIf="loading" class="spinner_box">
  <div class="lds-ring"><div></div><div></div><div></div><div></div></div>
</div>

app.component.scss

.main_container{
  margin: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  .video_box{
    width: 350px;
    height: auto;
  }

  .photoShow{
    width: 250px;
    height: 250px;
    display: flex;
    flex-direction: column;
    align-items: center;
    img{
      width: 100%;
    }
  }
}

button{
  margin-top: 20px;
  cursor: pointer;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 500;
  line-height: 25px;
  letter-spacing: 0.5px;
  width: 100%;
  max-width: 200px;
  height: 40px;
  border: none;
  background-color: #005db4d8 !important;
  color: white;
  &:focus{
    outline: none;
  }
  transition: all 200ms ;
}


////////SPINNER///

.lds-ring {
  display: inline-block;
  position: relative;
  width: 80px;
  height: 80px;
}
.lds-ring div {
  box-sizing: border-box;
  display: block;
  position: absolute;
  width: 64px;
  height: 64px;
  margin: 8px;
  border: 8px solid #005db4d8;
  border-radius: 50%;
  animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  border-color: #005db4d8 transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
  animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
  animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
  animation-delay: -0.15s;
}
@keyframes lds-ring {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.spinner_box{

  width: 100%;
  height: 100%;
  background: rgba(10, 10, 10, 0.2);;
  right: 0;
  top: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
}

Readme

Keywords

none

Package Sidebar

Install

npm i tm-ocr-photo

Weekly Downloads

1

Version

1.4.8

License

none

Unpacked Size

353 kB

Total Files

21

Last publish

Collaborators

  • talento-mobile