Skip to content
Snippets Groups Projects
Commit 40f0f158 authored by Yuriy Maksymets's avatar Yuriy Maksymets
Browse files

Matrix coefficient base for rect detection

parent 0d7603d5
No related branches found
No related tags found
No related merge requests found
import recognizeFromPoints, { Shapes } from "../src/shapes" import recognizeFromPoints, {
Shapes,
computeMatrixCoefficients,
} from "../src/shapes"
describe("shape recognition", () => { describe("shape recognition", () => {
describe("general", () => { describe("general", () => {
...@@ -9,6 +12,18 @@ describe("shape recognition", () => { ...@@ -9,6 +12,18 @@ describe("shape recognition", () => {
}) })
}) })
describe("matrix coefficients", () => {
test("should compute coefficients correctly", () => {
const points = [[0, 0], [0, 5], [0, 10], [10, 5]]
const coefficients = computeMatrixCoefficients(points)
expect(coefficients).toStrictEqual([
[1 / 4, 1 / 4, 1 / 4],
[0, 0, 0],
[0, 1 / 4, 0],
])
})
})
describe("lines", () => { describe("lines", () => {
test("should recognize a simple horizontal line", () => { test("should recognize a simple horizontal line", () => {
const points = [[0, 0], [100, 0]] const points = [[0, 0], [100, 0]]
......
...@@ -56,7 +56,98 @@ function constructHoughAccumulator(accumulator, x, y) { ...@@ -56,7 +56,98 @@ function constructHoughAccumulator(accumulator, x, y) {
} }
} }
function recognizeFromPoints(points) { function boundingCoords(points) {
const xs = points.map((p) => p[0])
const ys = points.map((p) => p[1])
return {
maxX: Math.max(...xs),
minX: Math.min(...xs),
maxY: Math.max(...ys),
minY: Math.min(...ys),
}
}
const MATRIX_SIZE = 3
function mArray(min, max) {
const step = (max - min) / MATRIX_SIZE
return Array(MATRIX_SIZE)
.fill(min)
.map((x, i) => x + step * (i + 1))
}
function getCluster([x, y], xBounds, yBounds) {
return {
x: xBounds.findIndex((bound) => x <= bound),
y: yBounds.findIndex((bound) => y <= bound),
}
}
function computeClusters(points, xBounds, yBounds) {
const clusters = Array(MATRIX_SIZE)
.fill(0)
.map(() =>
Array(MATRIX_SIZE)
.fill()
.map(() => []),
)
points.forEach((point) => {
const { x, y } = getCluster(point, xBounds, yBounds)
clusters[x][y].push(point)
})
return clusters
}
function clusterCoefficients(clusters, points) {
return clusters.map((rowCluster) =>
rowCluster.map((cluster) => cluster.length / points.length),
)
}
export function computeMatrixCoefficients(points) {
const { maxX, minX, maxY, minY } = boundingCoords(points)
const xBounds = mArray(minX, maxX)
const yBounds = mArray(minY, maxY)
const clusters = computeClusters(points, xBounds, yBounds)
const coefficients = clusterCoefficients(clusters, points)
return coefficients
}
function couldBeLine(points) {
return points.length >= 2
}
const RECT_THRESHOLD_CENTER = 0.05
const RECT_THRESHOLD_SIDE_VARIANCE = 0.2
function couldBeRect(points) {
if (points.length < 4) return false
const matrixCoefficients = computeMatrixCoefficients(points)
let [maxC, minC] = [0, 1]
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (!(i === j && j === 1)) {
maxC = Math.max(maxC, matrixCoefficients[i][j])
minC = Math.min(minC, matrixCoefficients[i][j])
}
}
}
if (
matrixCoefficients[1][1] < RECT_THRESHOLD_CENTER &&
maxC - minC < RECT_THRESHOLD_SIDE_VARIANCE
) {
return true
}
return false
}
function recognizeRect(points) {
return { points }
}
function recognizeLine(points) {
if (!(points && points.length)) return {} if (!(points && points.length)) return {}
const accum = Array(numAngleCells) const accum = Array(numAngleCells)
points.forEach((x) => constructHoughAccumulator(accum, ...x)) points.forEach((x) => constructHoughAccumulator(accum, ...x))
...@@ -74,6 +165,16 @@ function recognizeFromPoints(points) { ...@@ -74,6 +165,16 @@ function recognizeFromPoints(points) {
return {} return {}
} }
function recognizeFromPoints(points) {
if (couldBeRect(points)) {
return recognizeRect(points)
} else if (couldBeLine(points)) {
return recognizeLine(points)
}
return {}
}
export const Shapes = { export const Shapes = {
rectangle: "rect", rectangle: "rect",
line: "line", line: "line",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment