Created
September 23, 2022 20:12
-
-
Save lancegliser/d22089301cfa08d194e1ffd2007235d5 to your computer and use it in GitHub Desktop.
Typescript intersection over union
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: "); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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