Commit ad2ebd7f by vincent

restore drawFaceLandmarks + make FaceDetection extend ObjectDetection

parent adaed9e7
......@@ -4,7 +4,7 @@ import { TinyYolov2 } from '.';
import { FaceDetection } from './classes/FaceDetection';
import { FaceLandmarks68 } from './classes/FaceLandmarks68';
import { FullFaceDescription } from './classes/FullFaceDescription';
import { extractFaceTensors } from './extractFaceTensors';
import { extractFaceTensors } from './dom';
import { FaceDetectionNet } from './faceDetectionNet/FaceDetectionNet';
import { FaceLandmarkNet } from './faceLandmarkNet/FaceLandmarkNet';
import { FaceRecognitionNet } from './faceRecognitionNet/FaceRecognitionNet';
......
import { Dimensions, Rect } from 'tfjs-image-recognition-base';
export class FaceDetection {
private _score: number
private _box: Rect
private _imageWidth: number
private _imageHeight: number
import { Dimensions, ObjectDetection, Rect } from 'tfjs-image-recognition-base';
export class FaceDetection extends ObjectDetection {
constructor(
score: number,
relativeBox: Rect,
imageDims: Dimensions
) {
const { width, height } = imageDims
this._imageWidth = width
this._imageHeight = height
this._score = score
this._box = new Rect(
relativeBox.x * width,
relativeBox.y * height,
relativeBox.width * width,
relativeBox.height * height
)
}
public get score(): number {
return this._score
}
public get box(): Rect {
return this._box
}
public get imageWidth(): number {
return this._imageWidth
}
public get imageHeight(): number {
return this._imageHeight
}
public get relativeBox(): Rect {
return new Rect(
this._box.x / this._imageWidth,
this._box.y / this._imageHeight,
this._box.width / this._imageWidth,
this._box.height / this._imageHeight
)
}
public getScore() {
return this.score
}
public getBox() {
return this.box
}
public getImageWidth() {
return this.imageWidth
}
public getImageHeight() {
return this.imageHeight
}
public getRelativeBox() {
return this.relativeBox
}
public forSize(width: number, height: number): FaceDetection {
return new FaceDetection(
this._score,
this.getRelativeBox(),
{ width, height}
)
super(score, score, '', relativeBox, imageDims)
}
}
\ No newline at end of file
import { Point } from 'tfjs-image-recognition-base';
export function drawContour(
ctx: CanvasRenderingContext2D,
points: Point[],
isClosed: boolean = false
) {
ctx.beginPath()
points.slice(1).forEach(({ x, y }, prevIdx) => {
const from = points[prevIdx]
ctx.moveTo(from.x, from.y)
ctx.lineTo(x, y)
})
if (isClosed) {
const from = points[points.length - 1]
const to = points[0]
if (!from || !to) {
return
}
ctx.moveTo(from.x, from.y)
ctx.lineTo(to.x, to.y)
}
ctx.stroke()
}
\ No newline at end of file
import { getContext2dOrThrow, getDefaultDrawOptions, resolveInput } from 'tfjs-image-recognition-base';
import { FaceLandmarks } from '../classes/FaceLandmarks';
import { FaceLandmarks68 } from '../classes/FaceLandmarks68';
import { drawContour } from './drawContour';
import { DrawLandmarksOptions } from './types';
export function drawLandmarks(
canvasArg: string | HTMLCanvasElement,
faceLandmarks: FaceLandmarks | FaceLandmarks[],
options?: DrawLandmarksOptions
) {
const canvas = resolveInput(canvasArg)
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('drawLandmarks - expected canvas to be of type: HTMLCanvasElement')
}
const drawOptions = Object.assign(
getDefaultDrawOptions(options),
(options || {})
)
const { drawLines } = Object.assign({ drawLines: false }, (options || {}))
const ctx = getContext2dOrThrow(canvas)
const { lineWidth, color = 'blue' } = drawOptions
const faceLandmarksArray = Array.isArray(faceLandmarks) ? faceLandmarks : [faceLandmarks]
faceLandmarksArray.forEach(landmarks => {
if (drawLines && landmarks instanceof FaceLandmarks68) {
ctx.strokeStyle = color
ctx.lineWidth = lineWidth
drawContour(ctx, landmarks.getJawOutline())
drawContour(ctx, landmarks.getLeftEyeBrow())
drawContour(ctx, landmarks.getRightEyeBrow())
drawContour(ctx, landmarks.getNose())
drawContour(ctx, landmarks.getLeftEye(), true)
drawContour(ctx, landmarks.getRightEye(), true)
drawContour(ctx, landmarks.getMouth(), true)
return
}
// else draw points
const ptOffset = lineWidth / 2
ctx.fillStyle = color
landmarks.getPositions().forEach(pt => ctx.fillRect(pt.x - ptOffset, pt.y - ptOffset, lineWidth, lineWidth))
})
}
\ No newline at end of file
import * as tf from '@tensorflow/tfjs-core';
import { Rect, TNetInput, toNetInput } from 'tfjs-image-recognition-base';
import { FaceDetection } from './classes/FaceDetection';
import { FaceDetection } from '../classes/FaceDetection';
/**
* Extracts the tensors of the image regions containing the detected faces.
......
......@@ -7,7 +7,7 @@ import {
toNetInput,
} from 'tfjs-image-recognition-base';
import { FaceDetection } from './classes/FaceDetection';
import { FaceDetection } from '../classes/FaceDetection';
/**
* Extracts the image regions containing the detected faces.
......
export * from './drawContour'
export * from './drawLandmarks'
export * from './extractFaces'
export * from './extractFaceTensors'
export * from './types'
\ No newline at end of file
export type DrawLandmarksOptions = {
lineWidth?: number
color?: string,
drawLines?: boolean
}
\ No newline at end of file
......@@ -8,9 +8,8 @@ export * from 'tfjs-image-recognition-base';
export * from './classes';
export * from './dom'
export * from './euclideanDistance';
export * from './extractFaces'
export * from './extractFaceTensors'
export * from './faceDetectionNet';
export * from './faceLandmarkNet';
export * from './faceRecognitionNet';
......
import { bufferToImage, extractFaceTensors, Rect } from '../../src';
import { bufferToImage, extractFaceTensors, Rect } from '../../../src';
describe('extractFaceTensors', () => {
......
import { bufferToImage, createCanvasFromMedia, extractFaces, Rect } from '../../src';
import { bufferToImage, createCanvasFromMedia, extractFaces, Rect } from '../../../src';
describe('extractFaces', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment