Skip to content

Commit

Permalink
Added document detector for image files
Browse files Browse the repository at this point in the history
  • Loading branch information
yushulx committed Jul 23, 2024
1 parent d1c6817 commit 0f6e381
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 10 deletions.
5 changes: 5 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
"glob": "**/*",
"input": "./node_modules/dynamsoft-camera-enhancer/dist",
"output": "assets/dynamsoft-camera-enhancer"
},
{
"glob": "**/*",
"input": "./node_modules/dynamsoft-document-normalizer/dist",
"output": "assets/dynamsoft-document-normalizer"
}
],
"styles": [
Expand Down
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"dynamsoft-barcode-reader-bundle": "10.2.1000",
"dynamsoft-camera-enhancer": "^4.0.2",
"dynamsoft-capture-vision-std": "^1.2.10",
"dynamsoft-document-normalizer": "^2.2.10",
"dynamsoft-image-processing": "^2.2.30",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
Expand Down
8 changes: 6 additions & 2 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { RouterModule, Routes } from '@angular/router';
import { ProductListComponent } from './product-list/product-list.component';
import { BarcodeReaderComponent } from './barcode-reader/barcode-reader.component';
import { BarcodeScannerComponent } from './barcode-scanner/barcode-scanner.component';
import { FileDetectionComponent } from './file-detection/file-detection.component';
import { CameraDetectionComponent } from './camera-detection/camera-detection.component';

const routes: Routes = [
{ path: '', component: ProductListComponent },
{ path: 'barcode-reader', component: BarcodeReaderComponent },
{ path: 'barcode-scanner', component: BarcodeScannerComponent },
{ path: 'barcode-reader', component: BarcodeReaderComponent },
{ path: 'barcode-scanner', component: BarcodeScannerComponent },
{ path: 'file-detection', component: FileDetectionComponent },
{ path: 'camera-detection', component: CameraDetectionComponent },
];

@NgModule({
Expand Down
4 changes: 4 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { BarcodeReaderComponent } from './barcode-reader/barcode-reader.componen
import { BarcodeScannerComponent } from './barcode-scanner/barcode-scanner.component';
import { ProductListComponent } from './product-list/product-list.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { FileDetectionComponent } from './file-detection/file-detection.component';
import { CameraDetectionComponent } from './camera-detection/camera-detection.component';

// import {NgxBarcodeQrcodeModule} from 'ngx-barcode-qrcode';

Expand All @@ -18,6 +20,8 @@ import { TopBarComponent } from './top-bar/top-bar.component';
BarcodeScannerComponent,
ProductListComponent,
TopBarComponent,
FileDetectionComponent,
CameraDetectionComponent,

],
imports: [
Expand Down
Empty file.
1 change: 1 addition & 0 deletions src/app/camera-detection/camera-detection.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>camera-detection works!</p>
25 changes: 25 additions & 0 deletions src/app/camera-detection/camera-detection.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CameraDetectionComponent } from './camera-detection.component';

describe('CameraDetectionComponent', () => {
let component: CameraDetectionComponent;
let fixture: ComponentFixture<CameraDetectionComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CameraDetectionComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(CameraDetectionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
15 changes: 15 additions & 0 deletions src/app/camera-detection/camera-detection.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-camera-detection',
templateUrl: './camera-detection.component.html',
styleUrls: ['./camera-detection.component.css']
})
export class CameraDetectionComponent implements OnInit {

constructor() { }

ngOnInit(): void {
}

}
28 changes: 28 additions & 0 deletions src/app/file-detection/file-detection.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#imageview {
position: relative;
width: 20vw;
}

#image {
position: relative;
width: 100%;
height: 100%;
}

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

.container {
align-items: center;
border: 3px solid orange;
}

/* #normalizedImage {
width: 20vw;
} */
29 changes: 29 additions & 0 deletions src/app/file-detection/file-detection.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<span id="loading-status" style="font-size:x-large" [hidden]="isLoaded">Loading Library...</span>
<br />

<div class="row">

<label for="binary"> <input type="radio" name="templates" value="binary" (change)="onRadioChange($event)" />Black &
White </label>


<label for="grayscale"><input type="radio" name="templates" value="grayscale" (change)="onRadioChange($event)" />
Grayscale </label>

<label for="color"><input type="radio" name="templates" value="color" [checked]="true"
(change)="onRadioChange($event)" /> Color </label>
</div>

<input type="file" title="file" id="file" accept="image/*" (change)="onChange($event)" />

<div class="container">
<div id="imageview">
<img id="image" alt="" />
<canvas id="overlay"></canvas>
</div>

<div id="resultview">
<canvas id="normalizedImage"></canvas>
</div>

</div>
25 changes: 25 additions & 0 deletions src/app/file-detection/file-detection.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FileDetectionComponent } from './file-detection.component';

describe('FileDetectionComponent', () => {
let component: FileDetectionComponent;
let fixture: ComponentFixture<FileDetectionComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FileDetectionComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(FileDetectionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
118 changes: 118 additions & 0 deletions src/app/file-detection/file-detection.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { Component, OnInit } from '@angular/core';
import { OverlayManager } from '../overlay';
import { CapturedResult, CaptureVisionRouter, SimplifiedCaptureVisionSettings } from 'dynamsoft-barcode-reader-bundle';
import { DetectedQuadResultItem, EnumImageColourMode, NormalizedImageResultItem } from 'dynamsoft-document-normalizer';

@Component({
selector: 'app-file-detection',
templateUrl: './file-detection.component.html',
styleUrls: ['./file-detection.component.css']
})
export class FileDetectionComponent implements OnInit {
isLoaded = false;
overlay: HTMLCanvasElement | undefined;
context: CanvasRenderingContext2D | undefined;
cvr: CaptureVisionRouter | undefined;
overlayManager: OverlayManager;
points: any[] = [];
currentFile: File | undefined;
NormalizeDocument_Color: string = "NormalizeDocument_Color";
NormalizeDocument_Binary: string = "NormalizeDocument_Binary";
NormalizeDocument_Gray: string = "NormalizeDocument_Gray";

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

ngOnDestroy() {
}

ngOnInit(): void {
this.overlayManager.initOverlay(document.getElementById('overlay') as HTMLCanvasElement);
(async () => {
this.cvr = await CaptureVisionRouter.createInstance();
this.isLoaded = true;
})();
}

onRadioChange(event: Event) {
if (!this.cvr) {
return;
}

let target = event.target as HTMLInputElement;
let colorMode = EnumImageColourMode.ICM_COLOUR;
if (target.value === 'binary') {
colorMode = EnumImageColourMode.ICM_BINARY;
} else if (target.value === 'grayscale') {
colorMode = EnumImageColourMode.ICM_GRAYSCALE;
} else if (target.value === 'color') {
colorMode = EnumImageColourMode.ICM_COLOUR;
}

let cvr = this.cvr;
(async () => {
let settings: SimplifiedCaptureVisionSettings = await cvr.getSimplifiedSettings('NormalizeDocument_Default');
settings.documentSettings.colourMode = colorMode;
await this.cvr!.updateSettings('NormalizeDocument_Default', settings);
this.normalize(this.currentFile!, this.points);
})();
}

async normalize(file: File, points: any) {
if (this.cvr) {
let settings: SimplifiedCaptureVisionSettings = await this.cvr.getSimplifiedSettings('NormalizeDocument_Default');
settings.roi.points = points;
settings.roiMeasuredInPercentage = false;
await this.cvr!.updateSettings('NormalizeDocument_Default', settings);

this.cvr.capture(file, 'NormalizeDocument_Default').then((normalizedImagesResult: CapturedResult) => {
if (normalizedImagesResult.items.length === 0) { return; }
let result = normalizedImagesResult.items[0] as NormalizedImageResultItem;
let image = document.getElementById('normalizedImage') as HTMLCanvasElement;
image.width = result.imageData.width;
image.height = result.imageData.height;
const destinationContext = image.getContext('2d');
destinationContext?.drawImage(result.toCanvas(), 0, 0);
});
}
}

onChange(event: Event) {
const element = event.currentTarget as HTMLInputElement;
let fileList: FileList | null = element.files;
if (fileList) {
let file = fileList.item(0) as any;
if (file) {
this.currentFile = file;
let fr = new FileReader();
fr.onload = (event: any) => {
let image = document.getElementById('image') as HTMLImageElement;
if (image) {
image.src = event.target.result;
const img = new Image();

img.onload = async (event: any) => {
this.overlayManager.updateOverlay(img.width, img.height);
if (this.cvr) {
let capturedResult: CapturedResult = await this.cvr.capture(file, 'DetectDocumentBoundaries_Default');
if (capturedResult.items.length > 0) {
let result = capturedResult.items[0] as DetectedQuadResultItem;
this.points = result.location.points;
this.overlayManager.drawOverlay(
result.location,
''
);
this.normalize(file, this.points);
}
}
};
img.src = event.target.result;
}
};
fr.readAsDataURL(file);
}
}
}

}
38 changes: 31 additions & 7 deletions src/app/product-list/product-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,38 @@
<h2>Examples</h2>
<div *ngFor="let product of products">
<h3>
<div *ngIf="product.id === 'reader'; else elseBlock">
<a [title]="product.name + ' details'" [routerLink]="['/barcode-reader']">>
{{ product.name }}
</a>
<div>
<ng-template [ngIf]="product.id === 'reader'">
<a [title]="product.name + ' details'" [routerLink]="['/barcode-reader']">>
{{ product.name }}
</a>
</ng-template>
</div>
<ng-template #elseBlock><a [title]="product.name + ' details'" [routerLink]="['/barcode-scanner']">>
{{ product.name }}
</a></ng-template>

<div>
<ng-template [ngIf]="product.id === 'scanner'">
<a [title]="product.name + ' details'" [routerLink]="['/barcode-scanner']">>
{{ product.name }}
</a>
</ng-template>
</div>

<div>
<ng-template [ngIf]="product.id === 'file-detection'">
<a [title]="product.name + ' details'" [routerLink]="['/file-detection']">>
{{ product.name }}
</a>
</ng-template>
</div>

<div>
<ng-template [ngIf]="product.id === 'camera-detection'">
<a [title]="product.name + ' details'" [routerLink]="['/camera-detection']">>
{{ product.name }}
</a>
</ng-template>
</div>

</h3>

<p *ngIf="product.description">Description: {{ product.description }}</p>
Expand Down
Loading

0 comments on commit 0f6e381

Please sign in to comment.