diff --git a/docs/Features/Regions of interest/Centroid.md b/docs/Features/Regions of interest/Centroid.md new file mode 100644 index 00000000..cb7d37f7 --- /dev/null +++ b/docs/Features/Regions of interest/Centroid.md @@ -0,0 +1,17 @@ +--- +sidebar_position: 70 +--- + +_Center of mass of the current ROI._ + +[🔎 ROI options and parameters of `centroid` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#centroid 'github.io link') + +In image processing, centroid is the weighted average of all the coordinates that belong to the region of interest. + +Centroids can be useful for determining the location of an object within an image as well as for tracking the movement of objects over time. + +In ImageJS centroid is a ROI class accessor that returns a point: + +```ts +const centroid = roi.centroid; +``` diff --git a/docs/Features/Regions of interest/Convex Hull.md b/docs/Features/Regions of interest/Convex Hull.md new file mode 100644 index 00000000..ade26f5e --- /dev/null +++ b/docs/Features/Regions of interest/Convex Hull.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 0 +--- + +_Smallest convex polygon or polyhedron that contains region of interest._ + +[🎭 Mask options and parameters `getConvexHull` method](https://image-js.github.io/image-js-typescript/classes/Mask.html#getConvexHull 'github.io link') +[🔎 ROI options and parameters of `convexHull` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#convexHull 'github.io link') + +[Convex Hull](https://en.wikipedia.org/wiki/Convex_hull 'wikipedia link on convex hull') is a way of characterizing the shape of an image by determining which pixels are adjacent to other pixels of the same intensity. This is a good way to find convex features in an image. + +![Image input](./img/convexHull.svg) + +:::tip +To understand what convex hull is, picture a rubber band wrapped around your object. The shape of this rubber band will be the shape of your convex hull. +::: + +In ImageJS convex hull is a ROI class accessor that returns a `ConvexHull` object. + +| Property name | Description | Property type | +| -------------------------------------------------------------------------------------------------- | ---------------------------- | ------------- | +| [`points`](https://image-js.github.io/image-js-typescript/interfaces/ConvexHull.html#points) | points that form convex hull | `Point[]` | +| [`surface`](https://image-js.github.io/image-js-typescript/interfaces/ConvexHull.html#surface) | convex hull's surface | `number` | +| [`perimeter`](https://image-js.github.io/image-js-typescript/interfaces/ConvexHull.html#perimeter) | convex hull's perimeter | `number` | + +```ts +const convexHull = roi.convexHull; +``` + +It can also be a Mask method to calculate its convex hull: + +```ts +const convexHull = mask.getConvexHull(); +``` + +
Implementation + +Here's how convex hull algorithm is implemented in ImageJS: + +_Calculate border points_: ImageJS uses an algorithm to identify points that constitute regions' borders. + +_Sorting points lexicographically_: After finding border points, they get sorted in ascending order. + +_Build the lower hull_: Traverse the sorted list of points to build the lower hull of the convex hull. Use a stack to keep track of the points in the lower hull. For each point, check whether it forms a left or right turn with the previous two points in the stack. If it forms a right turn, pop the last point from the stack until a left turn is formed. Then push the current point onto the stack. + +_Build the upper hull_: Traverse the sorted list of points in reverse order to build the upper hull of the convex hull. Use the same stack as before. Again, ensure that the points in the stack form a convex hull. + +_Combine the lower and upper hulls_: The combined result of the lower and upper hulls is the convex hull of the entire set of points. + +
diff --git a/docs/Features/Regions of interest/EQPC.md b/docs/Features/Regions of interest/EQPC.md new file mode 100644 index 00000000..7c10df28 --- /dev/null +++ b/docs/Features/Regions of interest/EQPC.md @@ -0,0 +1,24 @@ +--- +sidebar_position: 60 +--- + +_Diameter of a circle that has the same area as the projection area of the region of interest._ + +[🔎 ROI options and parameters of `eqpc` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#eqpc 'github.io link') + +EQPC represents a circle of equal projection area. This means that it is a diameter of a circle that has the same area as an object of interest. +It is widely used for the evaluation of particles sizes from the projection area A of a non-spherical particle. + +![roi image](./img/roi.svg) + +The formula finds diameter from potential circle's surface: + +$$ +EQPC = 2\sqrt{\frac{Surface}{\pi}} +$$ + +In ImageJS EQPC is a ROI class accessor that returns a diameter length in pixels: + +```ts +const eqpcResult = roi.eqpc; +``` diff --git a/docs/Features/Regions of interest/Feret Diameters.md b/docs/Features/Regions of interest/Feret Diameters.md new file mode 100644 index 00000000..8f6fd922 --- /dev/null +++ b/docs/Features/Regions of interest/Feret Diameters.md @@ -0,0 +1,62 @@ +--- +sidebar_position: 10 +--- + +_The longest and shortest distances between two parallel lines that touch a region of interest._ + +[🎭 Mask options and parameters of `getFeret` method](https://image-js.github.io/image-js-typescript/classes/Mask.html#getFeret 'github.io link') +[🔎 ROI options and parameters of `feret` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#feret 'github.io link') + +[Feret diameters](https://en.wikipedia.org/wiki/Feret_diameter 'wikipedia link on feret diameter') are determined by measuring the minimum and the maximum distances between two parallel tangents that touch the boundary of the region of interest. +This measurement is commonly employed for the analysis of shapes and structures in images. + +:::tip +Feret diameters can be defined by the points as if the object was measured by [caliper](https://en.wikipedia.org/wiki/Calipers 'wikipedia link on caliper'). Therefore its other name, caliper diameter. +::: + +![Feret output](./img/feret.svg) + +In ImageJS Feret diameters are a ROI class accessor that return a Feret object: + +| Property name | Description | Property type | +| ------------------------------------------------------------------------------------------------- | ------------------------------ | --------------- | +| [`minDiameter`](https://image-js.github.io/image-js-typescript/interfaces/Feret.html#minDiameter) | minimum diameter | `FeretDiameter` | +| [`maxDiameter`](https://image-js.github.io/image-js-typescript/interfaces/Feret.html#maxDiameter) | maximum diameter | `FeretDiameter` | +| [`aspectRatio`](https://image-js.github.io/image-js-typescript/interfaces/Feret.html#aspectRatio) | ratio between diameter lengths | `number` | + +```ts +const feret = roi.feret; +``` + +It can also be a Mask method to calculate its feret's diameters: + +```ts +const feret = mask.getFeret(); +``` + +:::info +Each diameter in itself is also an object which has its own properties: + +| Property name | Description | Property type | +| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------- | +| [`angle`](https://image-js.github.io/image-js-typescript/interfaces/FeretDiameter.html#angle) | Angle between the diameter and a horizontal line in degrees. | `number` | +| [`calliperLines`](https://image-js.github.io/image-js-typescript/interfaces/FeretDiameter.html#calliperLines) | Calliper lines that pass by endpoints of Feret diameters. | `[[Point, Point], [Point, Point]]` | +| [`length`](https://image-js.github.io/image-js-typescript/interfaces/FeretDiameter.html#length) | length of the diameter | `number` | +| [`points`](https://image-js.github.io/image-js-typescript/interfaces/FeretDiameter.html#points) | start and end points of the diameter | `[Point, Point]` | + +::: + +
Implementation + +Here's how Feret diameter is implemented in ImageJS: + +_Finding convex hull points_: an algorithm is based on the fact that one of the lines is aligned with one of the convex hull sides. This significantly facilitates Feret's diameter's search. Here, a preexisting convex hull method is implemented.(see [convex hull page](./Convex%20Hull.md 'internal link on convex hull') for more information). + +_Rotating an object_: an object gets rotated parallel to the X-axis. It allows finding tilt angles of the diameters. It also simplifies search for points. After all the data is found, it just gets rotated back by the same angle to get actual result. + +_Calculating maximum distance between points_: the algorithm iterates through each point and looks for the biggest distance between other points of convex hull. For the minimum diameter it also compares it with the previous maximum value and if it is smaller, it becomes new current minimum diameter. +For maximum diameter it just calculates the maximum distance between points of convex hull. + +_Finding caliper lines_: First, region's extreme values are found among rotated points. For minimum these are X values, for maximum - Y values. After that, lines can be found rather easily. For minimum caliper lines lines have a common Y coordinate with feret points and they are situated at the extremities of an object, which is also easy to obtain, since the object is rotated. Same process for maximum diameter, but this time, it's an X coordinate which is common. + +
diff --git a/docs/Features/Regions of interest/Fill ratio.md b/docs/Features/Regions of interest/Fill ratio.md new file mode 100644 index 00000000..b0a6bb7c --- /dev/null +++ b/docs/Features/Regions of interest/Fill ratio.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 80 +--- + +[🔎 ROI options and parameters of `fillRatio` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#fillRatio 'github.io link') + +_Ratio of the actual filled space to the total available space._ + +Fill ratio represents the ratio of how much of region's surface is filled with holes. Basically it helps understanding the actual ROI shape and how it is affected by holes in it. For example, if an object does not have holes or cavities in it the fill ratio will be equal to 1. + +The ratio is calculated in a simple manner: + +$$ +fill Ratio = \frac{Surface}{Surface + HolesInfo.surface} +$$ + +Where $$HolesInfo.surface$$ is the surface property of the method that specifically calculates the information about ROI's holes. + +In ImageJS fill ratio is a ROI class accessor that returns a ratio: + +```ts +const fillRatio = roi.fillRatio; +``` diff --git a/docs/Features/Regions of interest/MBR.md b/docs/Features/Regions of interest/MBR.md new file mode 100644 index 00000000..66cec6aa --- /dev/null +++ b/docs/Features/Regions of interest/MBR.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 20 +--- + +_Smallest rectangle that fully encloses a region of interest, providing a bounding box with minimal area._ + +[🎭 Mask options and parameters of `getMbr` method](https://image-js.github.io/image-js-typescript/classes/Mask.html#getMbr 'github.io link') +[🔎 ROI options and parameters of `mbr` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#mbr 'github.io link') + +Minimum Bounding Rectangle(MBR) is the smallest rectangle which can fit the region of interest in question. + +![MBR output](./img/mbr.svg) + +MBR is relevant for such things as extracting features, detecting collisions or simply localizing objects. + +In ImageJS minimum bounding rectangle is a ROI class accessor that returns a `Mbr` object. + +| Property name | Description | Property type | +| ----------------------------------------------------------------------------------------------- | ------------------------------------ | ------------- | +| [`points`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#points) | points that form MBR | `Point[]` | +| [`perimeter`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#perimeter) | MBR's perimeter | `number` | +| [`surface`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#surface) | MBR's surface | `number` | +| [`height`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#height) | MBR's height | `number` | +| [`width`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#width) | MBR's width | `number` | +| [`angle`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#angle) | MBR's angle | `number` | +| [`aspectRatio`](https://image-js.github.io/image-js-typescript/interfaces/Mbr.html#aspectRatio) | ratio between MBR's width and height | `number` | + +```ts +const mbr = roi.mbr; +``` + +It can also be a Mask method to calculate its mbr: + +```ts +const mbr = mask.getMbr(); +``` + +
Implementation + +Here's how Minimum Bounding Rectangle is calculated in ImageJS: + +_Finding convex hull_:an algorithm is based on the fact that one of the MBR sides is aligned with one of the convex hull sides. + +_Rotating an object_: an object gets rotated parallel to the X-axis. It allows finding tilt angles of the diameters. It also facilitates calculation of the points. After all the data is found, it just gets rotated back by the same angle to get actual result. + +_Finding extremities_: since the object is rotated, it means that vertical lines will be perpendicular to the hull side in question. Therefore, for each side, algorithm finds extremities which in turn calculate into points, width and surface. + +
diff --git a/docs/Features/Regions of interest/PED.md b/docs/Features/Regions of interest/PED.md new file mode 100644 index 00000000..22370f47 --- /dev/null +++ b/docs/Features/Regions of interest/PED.md @@ -0,0 +1,24 @@ +--- +sidebar_position: 50 +--- + +_Diameter of a circle that has the same perimeter as the region of interest._ + +[🔎 ROI options and parameters of `ped` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#ped 'github.io link') + +PED represents a diameter of a circle that has the same perimeter as the particle image. +Similarly to [EQPC](./EQPC.md 'internal link on eqpc') it is used to evaluate ROI's sizes albeit from its perimeter and not surface. + +![roi image](./img/roi.svg) + +The formula is simple: + +$$ +PED = \frac{Perimeter}{\pi}; +$$ + +In ImageJS PED is a ROI class accessor that returns a diameter in pixels: + +```ts +const pedResult = roi.ped; +``` diff --git a/docs/Features/Regions of interest/Perimeter.md b/docs/Features/Regions of interest/Perimeter.md new file mode 100644 index 00000000..e5dd92d0 --- /dev/null +++ b/docs/Features/Regions of interest/Perimeter.md @@ -0,0 +1,31 @@ +--- +sidebar_position: 40 +--- + +_Total length of the object's outer borders._ + +[🔎 ROI options and parameters of `perimeter` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#perimeter 'github.io link') + +Although perimeter might seem like a straight-forward sum of border pixels this is not the case. +In ImageJS each pixel's perimeter gets calculated depending on the number of sides that the pixel is exposed to externally. + +This means: + +We count all the pixel sides that are outside the ROI (each side counts as 1). +If a pixel has 1 external side, this pixel's perimeter is equal to **1**. + +If a pixel has 2 external sides, we remove from the sum **(2 - √2) = ~0.59**. +Thus this **pixel's perimeter is equal to 2 - 0.59 = ~1.41**. + +If a pixel has 3 external sides, we remove from the sum **2 \* (2 - √2) = ~1.17**. +So this **pixel's perimeter is equal to 3 - 1.17 = ~1.83**. + +![Image](./img/download.svg) + +It is a basic tool that provides insight to region's size and length. + +In ImageJS Perimeter is a ROI accessor that returns a perimeter in pixels: + +```ts +const perimeter = roi.perimeter; +``` diff --git a/docs/Features/Regions of interest/Regions of interest.md b/docs/Features/Regions of interest/Regions of interest.md new file mode 100644 index 00000000..ccdd4fa7 --- /dev/null +++ b/docs/Features/Regions of interest/Regions of interest.md @@ -0,0 +1,17 @@ +This section is dedicated to analysis of mask and its specific regions. ImageJS is first and foremost an analyzer of particles and analysis of regions of interest. Therefore there are tools that help detecting particles as well as determining their size, shape position and direction. + +### Methods + +| Can be applied on | ROIs | Masks | +| ----------------------------------------------------------------------------------- | ------- | -------- | +| [Convex Hull(`convexHull`)](./Convex%20Hull.md 'internal link on convex hull') | ✅ | ✅ | +| [Feret diameter(`feret`)](./Feret%20Diameters.md 'internal link on feret diameter') | ✅ | ✅ | +| [Minimum Bounding Rectangle( `mbr` )](./MBR.md 'internal link on mbr') | ✅ | ✅ | +| [Perimeter(`perimeter`)](./Perimeter.md 'internal link on perimeter') | ✅ | ❌ | +| [EQPC(`eqpc`)](./EQPC.md 'internal link on eqpc') | ✅ | ❌ | +| [PED(`ped`)](./PED.md 'internal link on ped') | ✅ | ❌ | +| [Centroid(`centroid`)](./Centroid.md 'internal link on centroid') | ✅ | ❌ | +| [Fill ratio(`fillRatio`)](./Fill%20ratio.md 'internal link on fill ratio') | ✅ | ❌ | +| [Solidity(`solidity`)](./Solidity.md 'internal link on solidity') | ✅ | ❌ | +| [Roundness(`roundness`)](./Roundness.md 'internal link on roundness') | ✅ | ❌ | +| [Sphericity(`sphericity`)](./Sphericity.md 'internal link on sphericity') | ✅ | ❌ | diff --git a/docs/Features/Regions of interest/Roundness.md b/docs/Features/Regions of interest/Roundness.md new file mode 100644 index 00000000..a2130dc2 --- /dev/null +++ b/docs/Features/Regions of interest/Roundness.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 100 +--- + +_Quantifies the deviation of an object's shape from a perfect circle._ + +[🔎 ROI options and parameters of `roundness` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#roundness 'github.io link') + +Roundness is the measure of how closely the shape of an object approaches that of a mathematically perfect circle. +To compute it the formula is this: + +$$ +Roundness = \frac{4*Surface}{\pi * FeretDiameter_{Max}^2} +$$ + +Where $$FeretDiameter_{Max}$$ is the length of a maximum feret diameter. +Using roundness as a metric allows for consistent and objective comparisons between different shapes, facilitating research and analysis across various disciplines. + +In ImageJS roundness is a ROI class accessor that returns a ratio: + +```ts +const roundness = roi.roundness; +``` diff --git a/docs/Features/Regions of interest/Solidity.md b/docs/Features/Regions of interest/Solidity.md new file mode 100644 index 00000000..1a6e2e15 --- /dev/null +++ b/docs/Features/Regions of interest/Solidity.md @@ -0,0 +1,25 @@ +--- +sidebar_position: 90 +--- + +_Measure of the compactness of a region or object._ + +[🔎 ROI options and parameters of `solidity` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#solidity 'github.io link') + +The solidity describes the extent to which a shape is convex or concave. +It is calculated through this formula. + +$$ +Solidity = \frac{Surface}{ConvexHull.surface}; +$$ + +Where $ConvexHull.surface$ is the surface of ROIs convex hull. + +It provides insights into the shape irregularity and concavity of the structure. +The solidity of a completely convex shape is 1, the farther it deviates from 1, the greater the extent of concavity in the shape of the ROI. + +In ImageJS solidity is a ROI class accessor that returns a solidity index: + +```ts +const solidity = roi.solidity; +``` diff --git a/docs/Features/Regions of interest/Sphericity.md b/docs/Features/Regions of interest/Sphericity.md new file mode 100644 index 00000000..ee152f04 --- /dev/null +++ b/docs/Features/Regions of interest/Sphericity.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 110 +--- + +_Ratio that assesses how closely an object approaches the shape of a perfect sphere._ + +[🔎 ROI options and parameters of `sphericity` accessor](https://image-js.github.io/image-js-typescript/classes/Roi.html#sphericity 'github.io link') + +Sphericity is a measure of the degree to which a particle approximates the shape of a sphere, and is independent of its size. The value is always between 0 and 1. The less spheric the ROI is the smaller is the number. +It is calculated through this formula: + +$$ +Sphericity =\frac{ 2*\sqrt{Surface*\pi}}{Perimeter}; +$$ + +Sphericity has a similar role as [roundness](./Roundness.md 'internal link to roundness') and can be used as a reference for shape comparison. + +In ImageJS sphericity is a ROI class accessor that returns a sphericity index: + +```ts +const sphericity = roi.sphericity; +``` diff --git a/docs/Features/Regions of interest/img/convexHull.svg b/docs/Features/Regions of interest/img/convexHull.svg new file mode 100644 index 00000000..5d44b757 --- /dev/null +++ b/docs/Features/Regions of interest/img/convexHull.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Convex hull + +Surface: 7 + +Perimeter: 10.82 + diff --git a/docs/Features/Regions of interest/img/download.svg b/docs/Features/Regions of interest/img/download.svg new file mode 100644 index 00000000..0d040d5f --- /dev/null +++ b/docs/Features/Regions of interest/img/download.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Perimeter + +Perimeter: 16.14 + diff --git a/docs/Features/Regions of interest/img/feret.svg b/docs/Features/Regions of interest/img/feret.svg new file mode 100644 index 00000000..552cb247 --- /dev/null +++ b/docs/Features/Regions of interest/img/feret.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Feret diameters + +min: 2.82 + +max: 4.24 + +ψA: 0.6667 + diff --git a/docs/Features/Regions of interest/img/mbr.svg b/docs/Features/Regions of interest/img/mbr.svg new file mode 100644 index 00000000..4675d17b --- /dev/null +++ b/docs/Features/Regions of interest/img/mbr.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Minimum bonding rectangle + +Width: 5.66 + +Height: 4.24 + +Surface: 24 + +Perimeter: 19.80 + diff --git a/docs/Features/Regions of interest/img/roi.svg b/docs/Features/Regions of interest/img/roi.svg new file mode 100644 index 00000000..1fdec52e --- /dev/null +++ b/docs/Features/Regions of interest/img/roi.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Region of interest + +Surface: 16 + +External: 10 + +eqpc: 4.51 + +ped: 3.18 + diff --git a/project-words.txt b/project-words.txt index 6a4a3943..d9f1b14c 100644 --- a/project-words.txt +++ b/project-words.txt @@ -18,7 +18,10 @@ shanbhag thresholded RGBA bezier +EQPC +Feret +ROI's ROIs Feret canny -grayscaled \ No newline at end of file +grayscaled diff --git a/static/img/cellsDiv.jpg b/static/img/cellsDiv.jpg new file mode 100644 index 00000000..2417c78b Binary files /dev/null and b/static/img/cellsDiv.jpg differ diff --git a/static/img/roiTestingImage.png b/static/img/roiTestingImage.png new file mode 100644 index 00000000..894f68f8 Binary files /dev/null and b/static/img/roiTestingImage.png differ