物理超好玩

  • 首页
  • Noip学习助手
  • 书法字典APP下载
  • 资源列表
  • 格式化代码
  • 习题答案
  • 关于
物理超好玩
真诚面对自己
  1. 首页
  2. 程序设计
  3. 正文

用OpenCV的K-Means聚类对书法作品进行单字分割

2021年01月24日 1805点热度 7人点赞 0条评论

文本目录

  • 用OpenCV的K-Means聚类对书法作品进行单字分割
    • 在OpenCV中K-Means函数的使用方法
    • 程序运行过程
    • 程序代码
    • 效果分析

用OpenCV的K-Means聚类对书法作品进行单字分割

对书法作品的单字进行分割,是为书法字典APP提供字模的智能化方法。较传统的方法是运用直方图进行分割。在OpenCV中有轮廓查找(findContours)和聚类(kmeans)两个处理函数。理论上选对书法作品进行轮廓查找,再将距离相近的轮廓运进行聚类,每个类就是一个汉字。

在OpenCV中K-Means函数的使用方法

关于K-Means函数的介绍可以观看:理解K-Means聚类

函数原型:

retval, bestLabels, centers = kmeans(data, K, bestLabels, criteria, attempts, flags, centers=None)

函数参数:

data:  需要分类数据,最好是np.float32的数据,每个特征放一列。

K:  聚类个数

bestLabels:预设的分类标签或者None

criteria:迭代停止的模式选择,这是一个含有三个元素的元组型数。格式为(type, max_iter, epsilon) 其中,type有如下模式:

  • cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon,则停止。
  • cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter,则停止。
  • cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER:两者结合,满足任意一个结束。

attempts:重复试验kmeans算法次数,将会返回最好的一次结果

flags:初始中心选择,可选以下两种:

  • v2.KMEANS_PP_CENTERS:使用kmeans++算法的中心初始化算法,即初始中心的选择使眼色相差最大.详细可查阅kmeans++算法。(Use kmeans++ center initialization by Arthur and Vassilvitskii)
  • cv2.KMEANS_RANDOM_CENTERS:每次随机选择初始中心(Select random initial centers in each attempt.)

返回值:

compactness:紧密度,返回每个点到相应重心的距离的平方和

labels:结果标记,每个成员被标记为分组的序号,如 0,1,2,3,4...等

centers:由聚类的中心组成的数组

程序运行过程

  1. 确定要分割的汉字数量,即聚类个数
  2. 轮廓查找生成数据
  3. 定义停止条件
  4. K-Means分类
  5. 每个聚类的轮廓到一个列表中
  6. 聚类描边

程序代码

import numpy as np
import cv2 as cv

img = cv.imread('jk.jpg')

# 要分的聚类数
sampleCount = 50
# 要分割的字符数
charCount = 50

# 转换为灰度图
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 二值化
ret, thresh = cv.threshold(gray, 127, 255, 0)

# 反色,查找轮廓的要求是黑底白字
cv.bitwise_not(thresh, thresh)

# 发现轮廓
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

# 计算所有轮廓的面积和
pointCount = 0
for cnt in contours:
    pointCount += cv.contourArea(cnt)
# 最小面积,小于这个面积的轮廓将被删除
minPointSize = pointCount / charCount / 50

# 删除较小的轮廓
ucontours = []
for cnt in contours:
    if cv.contourArea(cnt) > minPointSize:
        ucontours.append(cnt)

cc = len(ucontours)
# 由每个轮廓的中心点生成二维数据
points = np.zeros((cc, 2), dtype=np.int)
p = 0
for cnt in ucontours:
    # 获取轮廓坐标和宽高
    x, y, w, h = cv.boundingRect(cnt)
    points[p][0] = x + w / 2
    points[p][1] = y + h / 2
    p += 1

# 转化为float数据
Z = np.float32(points)

# 定义
criteria = (cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret, labels, centers = cv.kmeans(Z, sampleCount, None, criteria, 10000, cv.KMEANS_PP_CENTERS)

print(ret)

# 将每个聚类的轮廓添加到同个列表中
cntlist = []
for i in range(sampleCount):
    cntlist.append([])
p = 0
for lb in labels:
    cntlist[lb[0]].append(ucontours[p])
    p += 1

rc = 255
bc = 0
# 轮廓描边
for i in range(sampleCount):
    cv.drawContours(img, cntlist[i], -1, (rc, bc, 0), 3)
    rc -= 5
    bc += 5

cv.imwrite('jkkm.png', img)

#cv.imshow('candy', img)
#cv.waitKey()



效果分析

从上图中可以看到,大多数字都准确的分割出来了,也有几处错误。如果能结合对图片进行膨胀,手动确定聚类中心,也许会更好些。

 

 

 

 

相关文章:

  1. 利用JavaCV+OpenCV的ANN_MLP神经网络训练识别MNIST手写数字
  2. 格式混乱的百度文库复制文本格式化工具
  3. 用Python下载PHET互动仿真程序
  4. 在JavaCV中合并两个Mat
  5. IDEA用Gradle打包GUI Form为可执行的jar
  6. U盘随身便携Git http服务器

订阅号“物理超好玩”
标签: K-Means OpenCV 书法作品 分割 聚类
最后更新:2021年01月24日

坚持

真诚的面对自己的内心。 确立志向;全力准备;清净无扰,最终成功。 尊重自我,做自己最擅长的事情,做自己最喜欢的事情。

点赞
< 上一篇
下一篇 >

坚持

真诚的面对自己的内心。 确立志向;全力准备;清净无扰,最终成功。 尊重自我,做自己最擅长的事情,做自己最喜欢的事情。

分类
  • NOIP (1)
  • 习题讲解 (9)
  • 克服沉迷 (2)
  • 游戏危害 (1)
  • 程序设计 (10)
  • 软件作品 (2)
标签聚合
计算题 javacv 初中物理 电学 gradle Idea OpenCV 串联电路
最新 热点 随机
最新 热点 随机
中国游戏防沉迷简史 转移注意力 认识游戏的危害 U盘随身便携Git http服务器 IDEA用Gradle打包GUI Form为可执行的jar 运用浮力求密度解题思路
在IDEA和Android Studio中用Gradle构建javacv开发环境 利用JavaCV+OpenCV的ANN_MLP神经网络训练识别MNIST手写数字 Idea中用gradle打包可执行的jar 运用浮力求密度解题思路 已知两组数据列方程组解题补充习题 NOIP信息学奥赛视频教程
  • 用OpenCV的K-Means聚类对书法作品进行单字分割
    • 在OpenCV中K-Means函数的使用方法
    • 程序运行过程
    • 程序代码
    • 效果分析

COPYRIGHT © 2021 物理超好玩. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

豫ICP备16037997号-2