computer-vision-project/src/main/kotlin/network/rs485/ben/computervision/IdentifiableEntity.kt

56 lines
1.9 KiB
Kotlin

package network.rs485.ben.computervision
import org.opencv.core.*
import org.opencv.imgproc.Imgproc
open class IdentifiableEntity(
entity: Entity,
private val dimensionProvider: DimensionProvider = CroppingDimensionProvider(entity.lines.toList()),
) {
companion object {
const val DIST_TRANSFORM_MASK_SIZE: Int = 3
// DIST_L2 is the simple euclidean distances
const val DIST_TRANSFORM_FUNC = Imgproc.DIST_L2
}
val rows: Int = dimensionProvider.maxY - dimensionProvider.minY + 1
val cols: Int = dimensionProvider.maxX - dimensionProvider.minX + 1
val rect: Rect
get() = Rect(dimensionProvider.minX, dimensionProvider.minY, cols, rows)
val lines = entity.lines.toList()
val transformedLines = lines.map {
transformPixel(it.first) to transformPixel(it.second)
}
val entityMask: Mat = Mat(rows, cols, CvType.CV_8UC1).also { maskMat ->
maskMat.setTo(COLOR_BLACK)
transformedColor(COLOR_WHITE, maskMat)
}
val distanceMat: Mat = Mat(rows, cols, CvType.CV_32FC1).also { distanceMat ->
Imgproc.distanceTransform(entityMask, distanceMat, DIST_TRANSFORM_FUNC, DIST_TRANSFORM_MASK_SIZE)
}
val minMaxDistance: Core.MinMaxLocResult by lazy { Core.minMaxLoc(distanceMat, entityMask) }
fun transformedColor(color: Scalar, image: Mat) {
transformedLines.forEach {
image.drawLine(it, color)
}
}
fun transformPixel(pixel: Pixel) = Pixel(pixel.x - dimensionProvider.minX, pixel.y - dimensionProvider.minY)
open fun release() {
entityMask.release()
distanceMat.release()
}
override fun toString(): String {
return "IdentifiableEntity($rect)"
}
}
internal inline fun <T> withIdEntity(entity: Entity, block: (identity: IdentifiableEntity) -> T): T =
IdentifiableEntity(entity).let { identity ->
autoclean(identity, identity::release, block)
}