An open API service indexing awesome lists of open source software.

https://github.com/beenotung/augment-image

Image augmentation library and cli for machine learning tasks
https://github.com/beenotung/augment-image

augmentation blur cli crop data-augmentation flip flipx flipy grayscale image machine-learning rotate scale shear typescript

Last synced: 6 months ago
JSON representation

Image augmentation library and cli for machine learning tasks

Awesome Lists containing this project

README

          

# augment-image

Image augmentation library and cli for machine learning tasks

[![npm Package Version](https://img.shields.io/npm/v/augment-image)](https://www.npmjs.com/package/augment-image)

## Features

- Rich combination of customizable image augmentation
- background color
- scale
- crop
- shear
- rotate
- gray-scale
- flipX
- flipY
- blur
- Typescript support
- Support usage from cli

## Installation

```bash
npm install augment-image
```

You can also install `augment-image` with [pnpm](https://pnpm.io/), [yarn](https://yarnpkg.com/), or [slnpm](https://github.com/beenotung/slnpm)

Note that optional dependency should not be disabled, sharp installs the os-specific native package as optional dependencies.

## Usage Example

**Run the cli with npx**:

```shell
npx augment-image [options]
```

**Available options**:

```
General:
-h, --help Show this help message and exit.
-v, --version Show the version number and exit.

Configuration:
-i, --init Initialize a configuration file.

Run Mode:
-r, --run Run the main logic of the application.
-s --srcDir Specify the source directory. Default is "./images/raw".
-o, --outDir Specify the output directory. Default is "./images/augments".
-q, --quiet Disable verbose logging. By default, verbose is enabled.
```

**Notes**:

- Use the --init option to generate a default config file.
- You can edit the config in "config.json" in the current directory.
- The config file must exist in the run mode.

**Use as library**:

```typescript
import {
aggressiveFilterGroupsOptions,
buildFilterGroups,
scanDirectory,
} from 'augment-image'

async function main() {
// use custom settings
let filterGroups = buildFilterGroups({
// RGBA background will be used for out-of-range content when rotate, scale, or shear
background: ['#ffffffff'],
scale: [
[0.5, 0.5],
[1.0, 0.5],
[2.0, 2.0],
],
crop: [
[Infinity, Infinity],
[100, 100],
[50, 50],
],
shear: [
[0, 0],
[-8, 0],
[+8, 0],
[0, -8],
[0, +8],
],
rotate: [0, 8, -8, 16, -16],
grayscale: 'both',
flipX: true,
blur: [0, 1, 2],
})

// use default settings
filterGroups = buildFilterGroups(aggressiveFilterGroupsOptions)

await scanDirectory({
srcDir: './images/raw',
outDir: './images/augmented',
filterGroups,
verbose: true,
})
}
main().catch(e => console.error(e))
```

## Typescript Signature

core functions and types

```typescript
import { Sharp } from 'sharp'

/** @description the core function that apply all combination of image augmentation filters */
export function augmentImage(
image: Sharp,
filterGroups: FilterGroup[],
): AsyncGenerator

/** @description scan images in `srcDir` and save the augmented images in `outDir` */
export function scanDirectory(options: {
srcDir: string
outDir: string
filterGroups: FilterGroup[]
/** @description default `true` */
verbose?: boolean
}): Promise<{
fileCount: number
}>

/** @description generate filter groups with variants based on the given options */
export function buildFilterGroups(
options: BuildFilterGroupsOptions,
): FilterGroup[]

export type BuildFilterGroupsOptions = {
/**
* @description for region that overflow when transform
* default `['#00000000']`
*/
background?: string[]
/**
* @description `Array<[w,h]>` in percentage, applied before crop
* e.g. `[[0.8,1.2]]` for 80% in width and 120% in height
* */
scale?: [w: number, h: number][]
/**
* @description `Array<[w,h]>` in pixel unit, applied before after scale
* e.g. `[[100,100],[100,150],[150,100]]`
*/
crop?: [w: number, h: number][]
/**
* @description `Array<[x,y]>` in degree, applied after crop
* e.g. `[[0,0],[-16,0],[+16,0],[0,-16],[0,+16]]`
* */
shear?: [x: number, y: number][]
/**
* @description in degree
* e.g. `[-15, 0, 15]`
* */
rotate?: number[]
grayscale?: 'always' | 'never' | 'both'
flipX?: boolean
flipY?: boolean
/**
* @description sigma range from 0 to 1000
* e.g. `[0, 1]`
* */
blur?: number[]
}

/** @description a reference setting that balance the number of image augmentation combination and the time cost */
export let aggressiveFilterGroupsOptions: BuildFilterGroupsOptions

type FilterGroup = {
name: string
variants: Filter[]
}

type Filter = {
(image: Sharp): Sharp[] | Sharp | Promise
}
```

helper functions

```typescript
import { Sharp } from 'sharp'

/** @description generate sequence of `number[]` */
export function range(args: {
/** @description inclusive */
from: number
/** @description inclusive */
to: number
/** @description can be positive or negative */
step: number
}): number[]

/** @description generate sequence of `number[]` */
export function rangeAround(args: {
center: number
/** @description inclusive */
range: number
/** @description can be positive or negative */
step: number
}): number[]

/** @description generate `[[a,a],[b,b]]` into combination of `[[a,a],[a,b],[b,a],[b,b]]` */
export function expandCropSize(
/** @description e.g. `[Infinity, 1000, 500, 300, 200, 100, 50]` */
size: number[],
): number[][]
```

## License

This project is licensed with [BSD-2-Clause](./LICENSE)

This is free, libre, and open-source software. It comes down to four essential freedoms [[ref]](https://seirdy.one/2021/01/27/whatsapp-and-the-domestication-of-users.html#fnref:2):

- The freedom to run the program as you wish, for any purpose
- The freedom to study how the program works, and change it so it does your computing as you wish
- The freedom to redistribute copies so you can help others
- The freedom to distribute copies of your modified versions to others