Skip to content

Commit

Permalink
Added MRZ scanner
Browse files Browse the repository at this point in the history
  • Loading branch information
yushulx committed Aug 5, 2024
1 parent 0679fa4 commit 8767982
Show file tree
Hide file tree
Showing 9 changed files with 9,328 additions and 294 deletions.
9,375 changes: 9,121 additions & 254 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"@angular/platform-browser": "~13.3.0",
"@angular/platform-browser-dynamic": "~13.3.0",
"@angular/router": "~13.3.0",
"dynamsoft-barcode-reader-bundle": "10.2.1000",
"dynamsoft-camera-enhancer": "^4.0.2",
"angular-barcode-qr-code-scanner": "file:",
"dynamsoft-barcode-reader-bundle": "^10.2.1000",
"dynamsoft-capture-vision-dnn": "^1.0.20",
"dynamsoft-capture-vision-std": "^1.2.10",
"dynamsoft-code-parser": "^2.2.10",
Expand All @@ -45,4 +45,4 @@
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.6.2"
}
}
}
46 changes: 24 additions & 22 deletions src/app/barcode-scanner/barcode-scanner.component.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
#videoview {
position: absolute;
width: 40vw;
height: 40vh;
}

#videoContainer {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
}

#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
object-fit: contain;
}

max-width: 720px;
max-height: 720px;
width: 720px;
height: 720px;
background-color: #eaeaea;
position: relative;
}

#videoContainer {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
}

#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
object-fit: contain;
}
5 changes: 4 additions & 1 deletion src/app/barcode-scanner/barcode-scanner.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
>
<br /> -->


<div class="select">
<label for="videoSource">Video source: </label>
<select id="videoSource" (change)="openCamera()"></select>
Expand All @@ -11,4 +12,6 @@
<div id="videoview">
<div class="dce-video-container" id="videoContainer"></div>
<canvas id="overlay"></canvas>
</div>
</div>

<div id="result"></div>
5 changes: 0 additions & 5 deletions src/app/barcode-scanner/barcode-scanner.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ export class BarcodeScannerComponent implements OnInit {
);
}

if (resultElement) {
resultElement.innerHTML = txts.join(', ');
}
} else {

if (resultElement) {
resultElement.innerHTML = txts.join(', ');
}
Expand Down
1 change: 0 additions & 1 deletion src/app/mrz-reader/mrz-reader.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export class MrzReaderComponent implements OnInit {

let item = items[i] as TextLineResultItem;
let localization = item.location;
console.log(localization);
this.overlayManager.drawOverlay(
localization,
''
Expand Down
13 changes: 7 additions & 6 deletions src/app/mrz-scanner/mrz-scanner.component.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.imageview {
#videoview {
max-width: 720px;
max-height: 720px;
width: 720px;
Expand All @@ -7,20 +7,21 @@
position: relative;
}

.imageview img {
display: block;
#videoContainer {
position: absolute;
width: 100%;
height: 100%;
object-fit: contain
z-index: 1;
}

.overlay {
#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain
z-index: 2;
object-fit: contain;
}

textarea {
Expand Down
22 changes: 21 additions & 1 deletion src/app/mrz-scanner/mrz-scanner.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
<p>mrz-scanner works!</p>
<div id="loading-indicator" class="loading-indicator" *ngIf="!isLoaded">
<div class="spinner"></div>
</div>

<div class="select">
<label for="videoSource">Video source: </label>
<select id="videoSource" (change)="openCamera()"></select>
</div>

<div class="container">
<div id="videoview">
<div class="dce-video-container" id="videoContainer"></div>
<canvas id="overlay"></canvas>
</div>

</div>


<div>
<textarea id="result"></textarea>
</div>
149 changes: 148 additions & 1 deletion src/app/mrz-scanner/mrz-scanner.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,162 @@
import { Component, OnInit } from '@angular/core';
import { OverlayManager } from '../overlay';
import { CameraEnhancer, CameraView, CapturedResult, CaptureVisionRouter, EnumCapturedResultItemType, Resolution } from 'dynamsoft-barcode-reader-bundle';
import { CodeParser, CodeParserModule } from 'dynamsoft-code-parser';
import { LabelRecognizerModule, TextLineResultItem } from 'dynamsoft-label-recognizer';
import { handleMrzParseResult } from '../utils';

const componentDestroyedErrorMsg = 'VideoCapture Component Destroyed';

@Component({
selector: 'app-mrz-scanner',
templateUrl: './mrz-scanner.component.html',
styleUrls: ['./mrz-scanner.component.css']
})
export class MrzScannerComponent implements OnInit {
isLoaded = false;
overlay?: HTMLCanvasElement;
context?: CanvasRenderingContext2D;
cameraInfo: any = {};
videoSelect: HTMLSelectElement | undefined;
overlayManager: OverlayManager;
cvr?: CaptureVisionRouter;
cameraEnhancer?: CameraEnhancer;
parser?: CodeParser;
isDestroyed = false;

constructor() { }
constructor() { this.overlayManager = new OverlayManager(); }

ngOnInit(): void {
this.videoSelect = document.querySelector('select#videoSource') as HTMLSelectElement;
this.overlayManager.initOverlay(document.getElementById('overlay') as HTMLCanvasElement);
(async () => {
await CodeParserModule.loadSpec("MRTD_TD1_ID");
await CodeParserModule.loadSpec("MRTD_TD2_FRENCH_ID");
await CodeParserModule.loadSpec("MRTD_TD2_ID");
await CodeParserModule.loadSpec("MRTD_TD2_VISA");
await CodeParserModule.loadSpec("MRTD_TD3_PASSPORT");
await CodeParserModule.loadSpec("MRTD_TD3_VISA");

await LabelRecognizerModule.loadRecognitionData("MRZ");
this.cvr = await CaptureVisionRouter.createInstance();
this.parser = await CodeParser.createInstance();
let ret = await this.cvr.initSettings('/assets/template.json');
console.log(ret);
await this.initBarcodeScanner();
})();
}

ngOnDestroy(): void {
this.isDestroyed = true;
try {
this.cvr?.dispose();
this.cameraEnhancer?.dispose();
} catch (_) { }
}

updateResolution(): void {
if (this.cameraEnhancer && this.overlayManager) {
let resolution: Resolution = this.cameraEnhancer.getResolution();
this.overlayManager.updateOverlay(resolution.width, resolution.height);
}
}

async initBarcodeScanner(): Promise<void> {
const cameraView: CameraView = await CameraView.createInstance();

this.cameraEnhancer = await CameraEnhancer.createInstance(cameraView);

let uiElement = document.getElementById('videoContainer');
if (uiElement) {
uiElement.append(cameraView.getUIElement());

cameraView.getUIElement().shadowRoot?.querySelector('.dce-sel-camera')?.setAttribute('style', 'display: none');
cameraView.getUIElement().shadowRoot?.querySelector('.dce-sel-resolution')?.setAttribute('style', 'display: none');

let cameras = await this.cameraEnhancer.getAllCameras();
this.listCameras(cameras);

if (this.isDestroyed) {
throw Error(componentDestroyedErrorMsg);
}
this.cvr?.setInput(this.cameraEnhancer);

// Define a callback for results.
this.cvr?.addResultReceiver({
onCapturedResultReceived: async (result: CapturedResult) => {
this.overlayManager.clearOverlay();
let txts: any = [];
let resultElement = document.getElementById('result');
try {
let localization;
let items = result.items
if (items.length > 0) {
for (var i = 0; i < items.length; ++i) {

if (items[i].type !== EnumCapturedResultItemType.CRIT_TEXT_LINE) {
continue;
}

let item = items[i] as TextLineResultItem;

txts.push(item.text);
localization = item.location;
this.overlayManager.drawOverlay(
localization,
''
);

let parseResults = await this.parser?.parse(item.text);
if (resultElement) {
resultElement.innerHTML = JSON.stringify(handleMrzParseResult(parseResults!)) + '\n';
}

break;
}

}
} catch (e) {
alert(e);
}
},
});

this.cameraEnhancer.on('played', () => {
this.updateResolution();
});
await this.openCamera();
if (this.isDestroyed) {
throw Error(componentDestroyedErrorMsg);
}
await this.cvr?.startCapturing('ReadMRZ');
if (this.isDestroyed) {
throw Error(componentDestroyedErrorMsg);
}

this.isLoaded = true;
}
}

async openCamera(): Promise<void> {
this.overlayManager.clearOverlay();
if (this.videoSelect) {
let deviceId = this.videoSelect.value;
if (this.cameraEnhancer) {
await this.cameraEnhancer.selectCamera(deviceId);
await this.cameraEnhancer.open();
}
}

}

listCameras(deviceInfos: any): void {
for (var i = 0; i < deviceInfos.length; ++i) {
var deviceInfo = deviceInfos[i];
var option = document.createElement('option');
option.value = deviceInfo.deviceId;
option.text = deviceInfo.label;
this.cameraInfo[deviceInfo.deviceId] = deviceInfo;
if (this.videoSelect) this.videoSelect.appendChild(option);
}
}
}

0 comments on commit 8767982

Please sign in to comment.