[Other] Refactor js submodule (#415)

* Refactor js submodule

* Remove change-log

* Update ocr module

* Update ocr-detection module

* Update ocr-detection module

* Remove change-log
This commit is contained in:
chenqianhe
2022-10-23 14:05:13 +08:00
committed by GitHub
parent 30971cf3fd
commit f2619b0546
273 changed files with 14697 additions and 5088 deletions

View File

@@ -0,0 +1,10 @@
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
]
}

View File

@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional'], // 使用预设的配置 https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/index.js
}

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,27 @@
module.exports = {
parser: '@typescript-eslint/parser', // 使用 ts 解析器
extends: [
'eslint:recommended', // eslint 推荐规则
'plugin:@typescript-eslint/recommended', // ts 推荐规则
'plugin:jest/recommended',
],
plugins: [
'@typescript-eslint',
'jest',
],
env: {
browser: true,
node: true,
es6: true,
},
parserOptions: {
project: 'tsconfig.eslint.json',
ecmaVersion: 2019,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true
}
},
rules: {}
}

View File

@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
etc
lib
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1 @@
auto-install-peers=true

View File

@@ -0,0 +1,15 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./lib/index.d.ts",
"bundledPackages": [],
"docModel": {
"enabled": true
},
"apiReport": {
"enabled": true
},
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "./lib/index.d.ts"
}
}

View File

@@ -0,0 +1,17 @@
import path from "path";
import chalk from "chalk";
export const paths = {
root: path.join(__dirname, '../'),
input: path.join(__dirname, '../src/index.ts'),
lib: path.join(__dirname, '../lib'),
}
export const log = {
progress: (text: string) => {
console.log(chalk.green(text))
},
error: (text: string) => {
console.log(chalk.red(text))
},
}

View File

@@ -0,0 +1,160 @@
import path from 'path'
import fse from 'fs-extra'
import { series } from "gulp"
import { paths, log } from "./build_package/util"
import rollupConfig from './rollup.config'
import { rollup } from 'rollup'
import {
Extractor,
ExtractorConfig,
ExtractorResult,
} from '@microsoft/api-extractor'
/**
* 这里是由于 'conventional-changelog' 未提供类型文件
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import conventionalChangelog from 'conventional-changelog'
interface TaskFunc {
// eslint-disable-next-line @typescript-eslint/ban-types
(cb: Function): void
}
const CHANGE_TRACE = ['paddlejs-models/facedetect', 'paddle-js-models/facedetect', 'paddlejs-models', 'paddle-js-models', 'all']
/**
* 删除 lib 文件
* @param cb
* @returns {Promise<void>}
*/
const clearLibFile: TaskFunc = async (cb) => {
fse.removeSync(paths.lib)
log.progress('Deleted lib file')
cb()
}
/**
* rollup 打包
* @param cb
*/
const buildByRollup: TaskFunc = async (cb) => {
const inputOptions = {
input: rollupConfig.input,
external: rollupConfig.external,
plugins: rollupConfig.plugins,
}
const outOptions = rollupConfig.output
const bundle = await rollup(inputOptions)
// 写入需要遍历输出配置
if (Array.isArray(outOptions)) {
for (const outOption of outOptions) {
await bundle.write(outOption)
}
cb()
log.progress('Rollup built successfully')
}
}
/**
* api-extractor 整理 .d.ts 文件
* @param cb
*/
const apiExtractorGenerate: TaskFunc = async (cb) => {
const apiExtractorJsonPath: string = path.join(__dirname, './api-extractor.json')
// 加载并解析 api-extractor.json 文件
const extractorConfig: ExtractorConfig = await ExtractorConfig.loadFileAndPrepare(apiExtractorJsonPath)
// 判断是否存在 index.d.ts 文件,这里必须异步先访问一边,不然后面找不到会报错
const isdtxExist: boolean = await fse.pathExists(extractorConfig.mainEntryPointFilePath)
// 判断是否存在 etc 目录api-extractor需要该目录存在
const isEtcExist: boolean = await fse.pathExists('./etc')
if (!isdtxExist) {
log.error('API Extractor not find index.d.ts')
return
}
if (!isEtcExist) {
fse.mkdirSync('etc');
log.progress('Create folder etc for API Extractor')
}
// 调用 API
const extractorResult: ExtractorResult = await Extractor.invoke(extractorConfig, {
localBuild: true,
// 在输出中显示信息
showVerboseMessages: true,
})
if (extractorResult.succeeded) {
// 删除多余的 .d.ts 文件
const libFiles: string[] = await fse.readdir(paths.lib)
for (const file of libFiles) {
if (file.endsWith('.d.ts') && !file.includes('index')) {
await fse.remove(path.join(paths.lib, file))
}
}
log.progress('API Extractor completed successfully')
// api-extractor 会生成 temp 文件夹,完成后进行删除
fse.ensureDirSync('temp')
fse.removeSync('temp')
cb()
} else {
log.error(`API Extractor completed with ${extractorResult.errorCount} errors`
+ ` and ${extractorResult.warningCount} warnings`)
}
}
/**
* 完成
* @param cb
*/
const complete: TaskFunc = (cb) => {
log.progress('---- end ----')
cb()
}
/**
* 生成 CHANGELOG
* @param cb
*/
export const changelog: TaskFunc = async (cb) => {
const checkTrace = (chunk: string) => {
for (const keyWord of CHANGE_TRACE) {
if (chunk.includes(keyWord)) {
return true
}
}
return false
}
const changelogPath: string = path.join(paths.root, 'CHANGELOG.md')
// 对命令 conventional-changelog -p angular -i CHANGELOG.md -w -r 0
const changelogPipe = await conventionalChangelog({
preset: 'angular',
releaseCount: 0,
})
changelogPipe.setEncoding('utf8')
const resultArray = ['# 更新日志\n\n']
changelogPipe.on('data', (chunk) => {
// 原来的 commits 路径是进入提交列表
chunk = chunk.replace(/\/commits\//g, '/commit/')
/**
* title 或 指定跟踪 才会写入CHANGELOG
*/
for (const log of chunk.split("\n")) {
if (log.includes('# ') || log.includes('### ') || checkTrace(log)) {
resultArray.push(log+"\n\n")
}
}
})
changelogPipe.on('end', async () => {
fse.createWriteStream(changelogPath).write(resultArray.join(''))
cb()
log.progress('CHANGELOG generation completed')
})
}
exports.build = series(clearLibFile, buildByRollup, apiExtractorGenerate, complete)

View File

@@ -0,0 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
}

View File

@@ -0,0 +1,77 @@
{
"name": "@paddle-js-models/facedetect",
"version": "3.0.1",
"description": "",
"main": "lib/index.js",
"module": "lib/index.esm.js",
"typings": "lib/index.d.js",
"files": [
"lib",
"LICENSE",
"CHANGELOG.md",
"README.md",
"README_cn.md"
],
"keywords": [],
"author": "",
"license": "ISC",
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"dev": "yalc publish --push",
"prepublish": "pnpm lint & pnpm test",
"prepublishOnly": "pnpm build",
"build": "gulp build",
"lint": "eslint --ext .js,.ts src --fix",
"api": "api-extractor run",
"test": "jest --coverage --verbose -u",
"changelog": "gulp changelog"
},
"devDependencies": {
"@babel/core": "^7.19.0",
"@babel/preset-env": "^7.19.0",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"@microsoft/api-extractor": "^7.30.0",
"@types/d3-polygon": "^3.0.0",
"@types/fs-extra": "^9.0.13",
"@types/gulp": "^4.0.9",
"@types/jest": "^29.0.1",
"@types/node": "^18.7.16",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"browserify": "^17.0.0",
"chalk": "4.1.2",
"commitlint": "^17.1.2",
"conventional-changelog-cli": "^2.2.2",
"eslint": "8.22.0",
"eslint-plugin-jest": "^27.0.4",
"fs-extra": "^10.1.0",
"gulp": "^4.0.2",
"gulp-clean": "^0.4.0",
"gulp-typescript": "6.0.0-alpha.1",
"gulp-uglify": "^3.0.2",
"husky": "^8.0.1",
"jest": "^29.0.3",
"lint-staged": "^13.0.3",
"rollup": "^2.79.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-eslint": "^7.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-string": "^3.0.0",
"rollup-plugin-typescript2": "^0.34.0",
"ts-jest": "^29.0.0",
"ts-node": "^10.9.1",
"tsify": "^5.0.4",
"typescript": "^4.8.3",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0"
},
"dependencies": {
"@paddlejs/paddlejs-backend-webgl": "^1.2.9",
"@paddlejs/paddlejs-core": "^2.2.0"
}
}

View File

@@ -0,0 +1,71 @@
import path from 'path'
import { RollupOptions } from 'rollup'
import rollupTypescript from 'rollup-plugin-typescript2'
import babel from 'rollup-plugin-babel'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import { eslint } from 'rollup-plugin-eslint'
import { DEFAULT_EXTENSIONS } from '@babel/core'
import pkg from './package.json'
import { paths } from "./build_package/util";
// rollup 配置项
const rollupConfig: RollupOptions = {
input: paths.input,
output: [
// 输出 commonjs 规范的代码
{
file: path.join(paths.lib, 'index.js'),
format: 'cjs',
name: pkg.name,
},
// 输出 es 规范的代码
{
file: path.join(paths.lib, 'index.esm.js'),
format: 'es',
name: pkg.name,
},
],
external: ['@paddlejs-mediapipe/opencv',
'@paddlejs/paddlejs-backend-webgl',
'@paddlejs/paddlejs-core',
'@types/node',
'd3-polygon',
'js-clipper',
'number-precision'],
// plugins 需要注意引用顺序
plugins: [
eslint({
throwOnError: true,
throwOnWarning: false,
include: ['src/**/*.ts'],
exclude: ['node_modules/**', 'lib/**', '*.js'],
}),
// 使得 rollup 支持 commonjs 规范,识别 commonjs 规范的依赖
commonjs(),
// 配合 commnjs 解析第三方模块
resolve({
// 将自定义选项传递给解析插件
customResolveOptions: {
moduleDirectory: 'node_modules',
},
}),
rollupTypescript(),
babel({
runtimeHelpers: true,
// 只转换源代码,不运行外部依赖
exclude: 'node_modules/**',
// babel 默认不支持 ts 需要手动添加
extensions: [
...DEFAULT_EXTENSIONS,
'.ts',
],
}),
],
}
export default rollupConfig

View File

@@ -0,0 +1,121 @@
import { Runner } from '@paddlejs/paddlejs-core';
import '@paddlejs/paddlejs-backend-webgl';
interface FeedShape {
fw: number;
fh: number;
}
export interface ModelConfig {
modelPath?: string;
mean?: number[];
std?: number[];
feedShape?: FeedShape;
}
interface NaturalSize {
naturalWidth: number;
naturalHeight: number;
}
export interface TransformData {
left: number;
width: number;
top: number;
height: number;
confidence: number;
}
// 默认模型数据
const defaultFeedShape: FeedShape = {
fw: 1024,
fh: 1024
};
const defaultModelConfig: ModelConfig = {
modelPath: 'https://paddlejs.cdn.bcebos.com/models/fuse/facedetect_opt/model.json',
mean: [0.407843137, 0.458823529, 0.482352941],
std: [0.5, 0.5, 0.5]
};
export class FaceDetector {
modelConfig: ModelConfig = defaultModelConfig;
feedShape: FeedShape = defaultFeedShape;
runner: Runner = null;
inputSize = {} as NaturalSize;
scale: number | undefined;
constructor(modeConfig?: ModelConfig) {
this.modelConfig = Object.assign(this.modelConfig, modeConfig);
this.feedShape = Object.assign(this.feedShape, modeConfig?.feedShape);
}
async init() {
this.runner = new Runner(this.modelConfig);
await this.runner.init();
}
async detect(
input: HTMLImageElement,
opts?
) {
this.inputSize.naturalWidth = input.naturalWidth;
this.inputSize.naturalHeight = input.naturalHeight;
const { shrink = 0.4, threshold = 0.6 } = Object.assign({}, opts);
const inputFeed = this.preprocess(input, shrink);
// 预测
const dataOut = await this.runner.predictWithFeed(inputFeed);
return this.postprocessor(dataOut, threshold);
}
preprocess(input: HTMLImageElement, shrink: number) {
// shrink --> scale
const scale = this.scale = Math.min(this.inputSize.naturalWidth, this.inputSize.naturalHeight) * shrink;
return this.runner.mediaProcessor.process(
input,
Object.assign({}, this.modelConfig, { scale }),
this.feedShape
);
}
postprocessor(dataOut, threshold: number) {
// data filter 筛掉小于阈值项
const dataFilt = dataOut.filter(item => item[1] && item[1] > threshold);
// data transform
return dataFilt.map(item => this.transformData(item));
}
transformData(data: Array<number>) {
const transformRes = {} as TransformData;
const { fw, fh } = this.feedShape;
const { naturalWidth, naturalHeight } = this.inputSize;
let dWidth;
let dHeight;
if (naturalWidth > naturalHeight) {
dHeight = this.scale;
dWidth = dHeight * naturalWidth / naturalHeight;
}
else {
dWidth = this.scale;
dHeight = dWidth * naturalHeight / naturalWidth;
}
const dx = (fw - dWidth) / 2;
const dy = (fh - dHeight) / 2;
transformRes.confidence = data[1];
transformRes.left = (data[2] * fw - dx) / dWidth;
transformRes.width = (data[4] - data[2]) * fw / dWidth;
transformRes.top = (data[3] * fh - dy) / dHeight;
transformRes.height = (data[5] - data[3]) * fh / dHeight;
return transformRes;
}
}
export function createImage(imgPath: string): Promise<HTMLImageElement> {
return new Promise(resolve => {
const image = new Image();
image.crossOrigin = 'anonymous';
image.onload = () => {
resolve(image);
};
image.src = imgPath;
});
}

View File

@@ -0,0 +1,12 @@
import assert from 'assert'
describe('Example:', () => {
/**
* Example
*/
describe('ExampleTest', () => {
test('Hello World!', () => {
assert.strictEqual('Hello World!', 'Hello World!')
})
})
})

View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"baseUrl": "./",
"resolveJsonModule": true
},
"include": [
"**/*.ts",
"**/*.js",
".eslintrc.js"
]
}

View File

@@ -0,0 +1,31 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
"target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"lib": [
"ESNext",
"DOM"
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
"resolveJsonModule": true, /* Enable importing .json files. */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
"outDir": "./lib", /* Specify an output folder for all emitted files. */
"removeComments": false, /* Disable emitting comments. */
"allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": [
"src"
]
}