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 withIdEntity(entity: Entity, block: (identity: IdentifiableEntity) -> T): T = IdentifiableEntity(entity).let { identity -> autoclean(identity, identity::release, block) }