Skip to content

Instantly share code, notes, and snippets.

@lancegliser
Created September 23, 2022 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lancegliser/d22089301cfa08d194e1ffd2007235d5 to your computer and use it in GitHub Desktop.
Save lancegliser/d22089301cfa08d194e1ffd2007235d5 to your computer and use it in GitHub Desktop.
Typescript intersection over union
import { getIntersectionOverUnion } from "./math";
describe("getIntersectionOverUnion", () => {
// Values from https://learnopencv.com/intersection-over-union-iou-in-object-detection-and-segmentation
it("should accept two sets of coordinates and return a numeric value", () => {
const intersectionOverUnion = getIntersectionOverUnion(
[1202, 123, 1650, 868],
[1162.0001, 92.0021, 1619.9832, 694.0033]
);
expect(intersectionOverUnion).toBe(0.6441);
});
it("should throw an error if a negative coordinate is supplied", () => {
// In the actual
expect(() => {
getIntersectionOverUnion(
[1202, -123, 1650, 868],
[1162.0001, 92.0021, 1619.9832, 694.0033]
);
}).toThrow("Invalid coordinate value: ");
// In the potential
expect(() => {
getIntersectionOverUnion(
[1202, 123, 1650, 868],
[1162.0001, -92.0021, 1619.9832, 694.0033]
);
}).toThrow("Invalid coordinate value: ");
});
});
/** Values arranged for matrix math: [x_1, y_1, x_2, y_2] */
type CoordinateArray = [number, number, number, number];
/**
* Compares the physical space of a set of coordinates and returns a float.
* IoU values range from 0 to 1. Where 0 means no overlap and 1 means perfect overlap.
*
* Most of the time "ground truth" and "prediction" are used in machine learning examples.
* Our usage will be more two versions of the truth as users attempt to draw their own reality.
* Our variables names are modified slightly reflect that.
*
* The article's suggested output is: 0.6441399913136432
* JS was a little off different: 0.6441399913136432
* We round a bit to avoid anything past < 1% to avoid that.
*
* Inspiration: https://learnopencv.com/intersection-over-union-iou-in-object-detection-and-segmentation
**/
export const getIntersectionOverUnion = (
actual: CoordinateArray,
potential: CoordinateArray
): number => {
// Ensure there are no invalid values
[...actual, ...potential].forEach((value) => {
if (value < 0) {
throw new Error(`Invalid coordinate value: ${value}`);
}
});
// coordinates of the area of intersection
const ix1 = Math.max(actual[0], potential[0]);
const iy1 = Math.max(actual[1], potential[1]);
const ix2 = Math.min(actual[2], potential[2]);
const iy2 = Math.min(actual[3], potential[3]);
const intersectionHeight = Math.max(iy2 - iy1 + 1, 0);
const intersectionWidth = Math.max(ix2 - ix1 + 1, 0);
const areaOfIntersection = intersectionHeight * intersectionWidth;
const actualHeight = actual[3] - actual[1] + 1;
const actualWidth = actual[2] - actual[0] + 1;
const potentialHeight = potential[3] - potential[1] + 1;
const potentialWidth = potential[2] - potential[0] + 1;
const areaOfUnion =
actualHeight * actualWidth +
potentialHeight * potentialWidth -
areaOfIntersection;
const intersectionOverUnion = areaOfIntersection / areaOfUnion;
const power = 10000;
return Math.round(intersectionOverUnion * power) / power;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment