image-js / image-js-typescript

Temporary repository to work on the migration of image-js to TypeScript
https://image-js.github.io/image-js-typescript/
MIT License
5 stars 5 forks source link

Propose an API to handle image stacks #410

Open opatiny opened 11 months ago

opatiny commented 11 months ago

Image stacks are array of images on which different methods can be applied. We want to create a new class Stack. The stacks were already implemented in image-js. Check how they were implemented and propose a new API for image-js-ts.

https://github.com/image-js/image-js/blob/8bfbcc524daafc35c35df62f5d18e7679deae7ee/src/stack/Stack.js

opatiny commented 11 months ago

Here is a first draft of an API to implement stacks in image-js-ts. Any feedback @stropitek , @targos , @lpatiny ?

export class Stack {
  /**
   * The number of images in stack.
   */
  public readonly size: number;

  public constructor(images: Image[], options: StackOptions = {}) {}

  /**
   * Return the image containing the minimum values of all the images in the stack for
   * each pixel .
   */
  public minImage(): Image {}

  /**
   * Return the image containing the maximum values of all the images in the stack for
   * each pixel .
   */
  public maxImage(): Image {}

  /**
   * Return the image containing the median values of all the images in the stack for
   * each pixel .
   */
  public medianImage(): Image {}

  /**
   * Return the image containing the average values of all the images in the stack for
   * each pixel .
   */
  public averageImage(): Image {}

  /**
   * Get the histograms of all the images of the stack.
   */
  public getHistograms(): Uint32Array {}
  /**
   * Get the global histogram of the stack.
   */
  public getHistogram(): Uint32Array {}

  /**
   * Return an array containing the maximum values of each image of the stack.
   */
  public max(): number[] {}

  /**
   * Return an array containing the minimum values of each image of the stack.
   */
  public min(): number[] {}

  /**
   * Align all the images of the stack on the image at the given index.
   * @param refIndex - The index of the reference image.
   */
  public alignImages(refIndex: number): Stack {}

  /**
   * Crop all the images of the stack to desired dimensions.
   * @param options - The cropping options.
   */
  public crop(options: CropOptions): Stack {}

  /**
   * Add all the images of the stack and return a 16 bits image containing the sum.
   */
  public sum(): Image {}
}

export interface CropOptions {
  /**
   * The top left corner of the crop rectangle.
   * @default {row: 0, column: 0}
   */
  origin?: Point;
  /**
   * The width of the crop rectangle.
   * @default image width
   */
  width?: number;
  /**
   * The height of the crop rectangle.
   * @default image height
   */
  height?: number;
}
targos commented 11 months ago

Some notes:

targos commented 11 months ago

Should all images of the stack have the same properties (dimensions, bidDepths, etc) ?

lpatiny commented 10 months ago

Should all images of the stack have the same properties (dimensions, bidDepths, etc) ?

Maybe not mandatory but most of the method should just throw if it is not the case. There could be a method that normalize them so that they have the same properties.

opatiny commented 10 months ago

There could be a method that normalize them so that they have the same properties.

What would you expect from a function normalizing the images?

opatiny commented 10 months ago

Should all images of the stack have the same properties (dimensions, bidDepths, etc) ?

I agree with @lpatiny that the images could have different dimensions, which could be made uniform with a normalize method. However it seems a lot easier to have the same bit depth and color model for all the images imo. Wdyt @targos ?

targos commented 10 months ago

Agreed. This should be validated when the stack is created and images are added to it.

opatiny commented 10 months ago

Would it be interesting to add a method allowing to read all images from a folder and directly create a stack with the images?

targos commented 10 months ago

Maybe but that's difficult to do right. Stacks have an order, which is not necessarily the same as folder iteration order. You also need to know what to read (what if there are multiple image formats in the folder? Or non image files ? ) too many questions that depend on the specific case

targos commented 10 months ago

You can also easily go out of memory with a large folder

stropitek commented 10 months ago

Were there known issues with extending Array, which is the implementation in legacy image-js?

It gives map, filter, forEach, reduce etc. out of the box.

With this implementation I suppose map would return an array of images (or something else) and not a Stack. We'd need another custom method that maps images to images by returning a Stack.

targos commented 10 months ago

I would not extend array. Its API surface is too large and we want something more abstract.