You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Kotlin的Android网格绘图应用:2D几何图形识别技术咨询

网格图形识别的非神经网络方案(Java/Kotlin适用)

一、基于几何特征的规则算法

针对网格中由离散单元格组成的图形,可以通过提取核心几何特征,用规则判断实现分类,比逐个检查单元格高效得多:

  • 边界框与宽高比:计算图形的最小包围矩形,通过宽高比区分正方形(接近1)、长方形(偏离1)、圆形(接近1)。
  • 填充率:图形占据的单元格数 ÷ 最小包围矩形的总单元格数。比如正方形填充率为1,圆形约0.78,三角形约0.5。
  • 角点数量:遍历图形单元格,统计“角点”——即周围8个方向中仅1-2个相邻图形单元格且方向突变的点。正方形有4个,三角形有3个,圆形几乎无明显角点。
  • 对称性:检查图形是否水平、垂直或对角线对称。正方形有4条对称轴,长方形2条,等腰三角形1条。

特征计算示例(Kotlin)

// grid为二维数组,true代表该单元格被绘制
fun getShapeFeatures(grid: Array<BooleanArray>): Pair<Float, Float> {
    var minRow = grid.size
    var maxRow = -1
    var minCol = grid[0].size
    var maxCol = -1
    var filledCells = 0

    grid.forEachIndexed { i, row ->
        row.forEachIndexed { j, isFilled ->
            if (isFilled) {
                filledCells++
                minRow = minOf(minRow, i)
                maxRow = maxOf(maxRow, i)
                minCol = minOf(minCol, j)
                maxCol = maxOf(maxCol, j)
            }
        }
    }

    val width = maxCol - minCol + 1
    val height = maxRow - minRow + 1
    val aspectRatio = width.toFloat() / height.toFloat()
    val fillRate = filledCells.toFloat() / (width * height)

    return Pair(aspectRatio, fillRate)
}

规则判断逻辑示例

  • 宽高比0.9-1.1且填充率≈1 → 正方形
  • 宽高比0.9-1.1且填充率0.75-0.8 → 圆形
  • 宽高比<0.6或>1.6且填充率≈1 → 长方形
  • 填充率0.45-0.55且角点数量为3 → 三角形

二、适用的轻量级库

  • Apache Commons Math:用其几何工具类计算图形的矩、对称性等统计特征,辅助分类判断。
  • JTS Topology Suite:将网格单元格转换为点集/多边形,计算面积、周长、顶点数等拓扑属性,方便图形匹配(需适配移动端环境)。
  • SimpleCV:提供基础几何形状识别工具,支持离散图形的特征提取,适合Android轻量场景。

三、优化逐个检查的技巧

如果坚持自定义逻辑,可通过以下方式简化:

  • 提取轮廓优先:先找出图形的边缘单元格(周围存在空白的绘制单元格),仅处理边缘部分,减少计算量。
  • 模板匹配:预定义各类图形的网格模板(如3x3正方形、5x5圆形),将用户绘制图形对齐缩放后,计算与模板的重合率,超过阈值则判定为对应图形。

模板匹配示例(Kotlin)

// 预定义3x3正方形模板
val squareTemplate = arrayOf(
    booleanArrayOf(true, true, true),
    booleanArrayOf(true, true, true),
    booleanArrayOf(true, true, true)
)

fun calculateMatchRate(drawnGrid: Array<BooleanArray>, template: Array<BooleanArray>): Float {
    var matchCount = 0
    val totalCells = template.size * template[0].size
    for (i in template.indices) {
        for (j in template[i].indices) {
            if (drawnGrid[i][j] == template[i][j]) matchCount++
        }
    }
    return matchCount.toFloat() / totalCells
}

内容的提问来源于stack exchange,提问作者aDragon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:23:21