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

Shape recognition code cleanup

parent 61c598f4
No related branches found
No related tags found
1 merge request!65Simple shape recognition
Pipeline #106321 failed
const getDistance = (a, b) => {
if (!(a && b)) return 0
return Math.sqrt(
(a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]),
)
}
// function dtor(a) {
// return (Math.PI * a) / 180
// }
// function cos(a) {
// return Math.cos(dtor(a))
// }
// function sin(a) {
// return Math.sin(dtor(a))
// }
// const angleStep = 90
// const numAngleCells = 180 / angleStep
// const rhoMax = 10000
// function findMaxInHough(accum, threshold) {
// let max = 0
// // let bestRho = 0
// let bestTheta = 0
// for (let i = 0; i < numAngleCells; i++) {
// if (!accum[i]) continue
// for (let j = 0; j < accum[i].length; j++) {
// if (accum[i][j] > max) {
// max = accum[i][j]
// bestTheta = i
// }
// }
// }
// bestTheta *= angleStep
const LINE_ANGLE_THRESHOLD = Math.PI / 6
const VECTOR_LEN_THRESHOLD_FRACTION = 0.3
// if (max > threshold) {
// return bestTheta
// }
// return undefined
// }
const RECT_MATRIX_SIZE = 3
const RECT_MATRIX_CENTER_RATIO = 0.65
// function constructHoughAccumulator(config, accumulator, x, y) {
// for (let thetaIndex = 0; thetaIndex < numAngleCells; thetaIndex++) {
// const theta = thetaIndex * angleStep
// let rho = x * cos(theta) + y * sin(theta)
// rho = Math.floor(rho)
// rho += rhoMax
// rho >>= 1
// rho /= config.rhoStep
// rho = Math.floor(rho)
// if (accumulator[thetaIndex] == undefined) accumulator[thetaIndex] = []
// if (accumulator[thetaIndex][rho] == undefined) {
// accumulator[thetaIndex][rho] = 1
// } else {
// accumulator[thetaIndex][rho]++
// }
// }
// }
const RECT_THRESHOLD_CENTER = 0
const RECT_THRESHOLD_SIDE_VARIANCE = 0.25
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),
}
function getDistance([x0, y0], [x1, y1]) {
return Math.hypot(x1 - x0, y1 - y0)
}
function vectorLength([x, y]) {
......@@ -84,42 +24,20 @@ function angleBetweenVectors(p1, p2) {
return Math.acos((x0 * x1 + y0 * y1) / (vectorLength(p1) * vectorLength(p2)))
}
const LINE_ANGLE_THRESHOLD = Math.PI / 6
const VECTOR_LEN_THRESHOLD_FRACTION = 0.3
function couldBeLine(points) {
if (points.length < 2) return false
const vectorThreshold = Math.floor(
points.length * VECTOR_LEN_THRESHOLD_FRACTION,
)
const pivot = points[0]
let cumulativeThreshold = 0
for (let i = 2; i < points.length; i++) {
const p1 = points[i - 1]
const p2 = points[i]
const d1 = diffVector(pivot, p1)
const d2 = diffVector(p1, p2)
const d2Len = vectorLength(d2)
const angle = angleBetweenVectors(d1, d2)
if (Math.abs(angle) > LINE_ANGLE_THRESHOLD) {
if (cumulativeThreshold < vectorThreshold && d2Len < vectorThreshold) {
cumulativeThreshold += d2Len
continue
}
return false
}
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),
}
return true
}
const MATRIX_SIZE = 3
const MATRIX_CENTER_RATIO = 0.65
function mArray(min, max) {
function matrixBoundsArray(min, max) {
const d = max - min
const centerSegmentSize = d * MATRIX_CENTER_RATIO
const centerSegmentSize = d * RECT_MATRIX_CENTER_RATIO
const smallStep = (d - centerSegmentSize) / 2
const p = [min + smallStep, min + smallStep + centerSegmentSize, max]
return p
......@@ -133,10 +51,10 @@ function getCluster([x, y], xBounds, yBounds) {
}
function computeClusters(points, xBounds, yBounds) {
const clusters = Array(MATRIX_SIZE)
const clusters = Array(RECT_MATRIX_SIZE)
.fill(0)
.map(() =>
Array(MATRIX_SIZE)
Array(RECT_MATRIX_SIZE)
.fill()
.map(() => ({ arr: [], sum: 0 })),
)
......@@ -164,16 +82,13 @@ function clusterCoefficients(clusters) {
export function computeMatrixCoefficients(points, boundingRect) {
const { maxX, minX, maxY, minY } = boundingRect
const xBounds = mArray(minX, maxX)
const yBounds = mArray(minY, maxY)
const xBounds = matrixBoundsArray(minX, maxX)
const yBounds = matrixBoundsArray(minY, maxY)
const clusters = computeClusters(points, xBounds, yBounds)
const coefficients = clusterCoefficients(clusters, points)
return coefficients
}
const RECT_THRESHOLD_CENTER = 0
const RECT_THRESHOLD_SIDE_VARIANCE = 0.25
function couldBeRect(points) {
if (points.length < 4) return false
......@@ -181,8 +96,8 @@ function couldBeRect(points) {
const matrixCoefficients = computeMatrixCoefficients(points, boundingRect)
let [maxC, minC] = [0, 1]
for (let i = 0; i < MATRIX_SIZE; i++) {
for (let j = 0; j < MATRIX_SIZE; j++) {
for (let i = 0; i < RECT_MATRIX_SIZE; i++) {
for (let j = 0; j < RECT_MATRIX_SIZE; j++) {
if (!(i === j && j === 1)) {
maxC = Math.max(maxC, matrixCoefficients[i][j])
minC = Math.min(minC, matrixCoefficients[i][j])
......@@ -199,6 +114,33 @@ function couldBeRect(points) {
return undefined
}
function couldBeLine(points) {
if (points.length < 2) return false
const vectorThreshold = Math.floor(
points.length * VECTOR_LEN_THRESHOLD_FRACTION,
)
const pivot = points[0]
let cumulativeThreshold = 0
for (let i = 2; i < points.length; i++) {
const p1 = points[i - 1]
const p2 = points[i]
const d1 = diffVector(pivot, p1)
const d2 = diffVector(p1, p2)
const d2Len = vectorLength(d2)
const angle = angleBetweenVectors(d1, d2)
if (Math.abs(angle) > LINE_ANGLE_THRESHOLD) {
if (cumulativeThreshold < vectorThreshold && d2Len < vectorThreshold) {
cumulativeThreshold += d2Len
continue
}
return false
}
}
return true
}
function recognizeRect(points, rectDetectionData) {
const { minX, minY, maxX, maxY } = rectDetectionData.boundingRect
return {
......@@ -227,33 +169,6 @@ function recognizeLine(points) {
lastPoint: p2.slice(0, 2),
}
}
// const MAX_RHO_STEP = 50
// const MIN_RHO_STEP = 5
// function rhoStepForPoints(points) {
// return points.length > 50 ? MAX_RHO_STEP : MIN_RHO_STEP
// }
// function recognizeLineHough(points) {
// if (!(points && points.length)) return {}
// const accum = Array(numAngleCells)
// const houghConfig = {
// rhoStep: rhoStepForPoints(points),
// }
// points.forEach((x) => constructHoughAccumulator(houghConfig, accum, ...x))
// const angle = findMaxInHough(accum, points.length - 10)
// if (angle !== undefined) {
// return {
// shape: Shapes.line,
// angle: 90 - angle,
// hough: accum,
// points,
// }
// }
// return {}
// }
function recognizeFromPoints(points) {
const rectDetectData = couldBeRect(points)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment