文章目录

  • 1. 前言
  • 2. 图像的矩特征
  • 3. 采集样本
  • 4. 模型训练
  • 5. 模型应用

1. 前言

文本识别早已经不是问题了,不过却不能直接应用于象棋棋子的识别,因为棋盘上的棋子是随机摆放上去的,不能保证棋子上的文字总是保持一个固定的角度。识别棋子的关键是找到具有“旋转不变性”的特征——无论棋子旋转多少度,其特征总是稳定的。

2. 图像的矩特征

矩是概率与统计中的一个概念,是随机变量的一种数字特征。如果把二维灰度图像视为有质量的平板,像素的灰度值ppp代表平板的密度,那么灰度图像就可以用二维灰度密度函数 p=f(x,y)p=f(x,y)p=f(x,y) 来表示。通过计算图像的零阶矩、一阶矩、二阶矩、三阶矩,即可获得被称为不变矩的七个高度浓缩的图像特征。不变矩具有平移、灰度、尺度、旋转不变性。

以下代码给出了计算图像不变矩的函数,基于OpenCV提供的两个函数实现,返回包含七个高度浓缩的图像特征的数组。因为图像不变矩的动态范围过大,默认返回的是不变矩的对数。

import cv2
import numpy as npdef humoments(img_gray, log=True):"""返回图像7个不变矩"""hu = cv2.HuMoments(cv2.moments(img_gray))[:,0]if log:hu = np.log(np.abs(hu))return hu

以下面四个角度的棋子“车”为例,不管角度如何,它们的不变矩具有很强的相关性。

-6.979, -21.904, -29.739, -28.555, -57.703, -39.707, -60.654
-6.945, -21.576, -29.658, -28.057, -57.050, -38.891, -57.633
-6.925, -21.083, -28.879, -27.764, -56.091, -38.464, -58.305
-6.978, -21.966, -29.773, -28.337, -57.442, -39.753, -58.575

3. 采集样本

选择不同角度、光照条件,对棋子拍照,不同照片上的棋子尽可能保持相同的尺寸。使用圆检测技术找到棋子,裁切、高斯模糊、二值化,通过旋转抖动生成多个样本,将其不变特征矩保存到样本集,其分类保存到标签集。最后,样本数据集保存成名为cchessman.npz的本地文件。

# -*- coding: utf-8 -*-import os
import cv2
from PIL import Image
import numpy as npdef humoments(img_gray, log=True):"""返回图像7个不变矩"""hu = cv2.HuMoments(cv2.moments(img_gray))[:,0]if log:hu = np.log(np.abs(hu))return hudef jitter(im_cv, theta):"""随机旋转和抖动,返回新的图像"""#theta = np.random.random()*360dx, dy = np.random.randint(0, 5, 2) - 2im_pil = Image.fromarray(im_cv)im_pil = im_pil.rotate(theta, translate=(dx, dy))im = np.array(im_pil)im[im==0] = 240im = np.where(im>128, 240, 15).astype(np.uint8)return imif __name__ == '__main__':# 定义一个96x96像素的掩码,用以滤除棋子周边的无效像素_mask = np.empty((96,96), dtype=np.bool)_mask.fill(False)for i in range(96):for j in range(96):if np.hypot((i-48), (j-48)) > 42:_mask[i,j] = Truetarget = list() # 分类结果集data = list() # 样本数据集chessman = ['车','马','炮','兵','卒','士','相','象','将','帅']files = [('res/ju.jpg', 0, 12),('res/ma.jpg', 1, 12),('res/pao.jpg', 2, 12),('res/bing.jpg', 3, 15),('res/zu.jpg', 4, 15),('res/shi.jpg', 5, 12),('res/rxiang.jpg', 6, 6),('res/bxiang.jpg', 7, 6),('res/jiang.jpg', 8, 3),('res/shuai.jpg', 9, 3)]for fn, idx, count in files:print('------------------------')print(fn)img = cv2.imread(fn)img_gray = cv2.imread(fn, cv2.IMREAD_GRAYSCALE)# 圆检测circles = cv2.HoughCircles(img_gray, cv2.HOUGH_GRADIENT, 1, 200, param1=100, param2=50, minRadius=90, maxRadius=140)circles = np.int_(np.around(circles))print(circles)for i, j, r in circles[0]:cv2.circle(img, (i, j), r, (0, 255, 0), 2)cv2.circle(img, (i, j), 2, (0, 0, 255), 3)piece = cv2.resize(img_gray[j-r:j+r, i-r:i+r], (96,96))piece[_mask] = 240piece = cv2.GaussianBlur(piece, (5,5), 0)piece = np.where(piece>128, 240, 15).astype(np.uint8)cv2.imwrite('res/chessman/%d_%d_%d.jpg'%(idx, i, j), piece)for theta in range(360):data.append(humoments(jitter(piece, theta)))target.append(idx)cv2.imshow('image', img)cv2.waitKey(0)cv2.destroyAllWindows()target = np.array(target)data = np.stack(data, axis=0)np.savez('cchessman.npz', target=target, data=data)

代码运行中,每处理一张图片,显式一次圆检测结果。如下图所示。

4. 模型训练

使用随机森林分类器,简单设置一下参数,就可以取得不错的训练效果。使用交叉验证的代码如下。

# -*- coding: utf-8 -*-import numpy as np
from sklearn.model_selection import cross_val_score, KFold
from sklearn.ensemble import RandomForestClassifierds = np.load('cchessman.npz')
X = ds['data']
y = ds['target']cv = KFold(n_splits=10, shuffle=True, random_state=0)
rfc = RandomForestClassifier()
rfc_scroe = cross_val_score(rfc, X, y, cv=cv)
print(rfc_scroe)
print(rfc_scroe.mean())

交叉验证结果显式,模型精度居然高达99.9%。

[1.         0.99971065 0.99971065 0.99971065 0.99971065 0.99942130.9994213  0.99971065 1.         0.9994213 ]
0.9996817129629629

5. 模型应用

新拍一张全家福,验证一下模型的泛化能力。

总共10个棋子,每个棋子随机旋转10次,生成100个测试样本。测试结果表明,准确率99%。

(34560, 7)
[[[ 534  756  119][ 468  412  128][ 208  640  128][1140  620  128][ 800  524  119][ 270  998  132][ 716  184  122][ 622 1106  123][1046  284  125][ 888  866  134]]]
['象', '象', '象', '象', '象', '象', '象', '象', '象', '象']
['卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒']
['车', '车', '车', '车', '车', '车', '车', '士', '车', '车']
['马', '马', '马', '马', '炮', '马', '马', '马', '马', '马']
['相', '相', '相', '相', '相', '相', '相', '相', '相', '相']
['士', '士', '士', '士', '士', '士', '士', '士', '士', '士']
['将', '将', '将', '将', '将', '将', '将', '将', '将', '将']
['帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅']
['兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵']
['炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮']

用机器学习的分类算法识别象棋棋子——兼论旋转不变性相关推荐

  1. [Python从零到壹] 十四.机器学习之分类算法五万字总结全网首发(决策树、KNN、SVM、分类对比实验)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  2. 机器学习分类算法_达观数据:5分钟带你理解机器学习及分类算法

    1.本文介绍内容:什么是机器学习,机器学习有哪些分类算法,分类算法之k-近邻,决策树,随机森林2.本文适合人群:本文通过通俗易懂的语言和例子介绍核心思想,不拽高大上的名词,适合于不懂机器学习的小白3. ...

  3. 机器学习5—分类算法之随机森林(Random Forest)

    随机森林(Random Forest) 前言 一.随机森林 1.什么是随机森林 2.随机森林的特点 3.随机森林的生成 二.随机森林的函数模型 三.随机森林算法实现 1.数据的读取 2.数据的清洗和填 ...

  4. 机器学习中分类算法的优缺点

    决策树 一.  决策树优点 1.决策树易于理解和解释,可以可视化分析,容易提取出规则. 2.可以同时处理标称型和数值型数据. 3.测试数据集时,运行速度比较快. 4.决策树可以很好的扩展到大型数据库中 ...

  5. DNS通道检测 国内学术界研究情况——研究方法:基于特征或者流量,使用机器学习决策树分类算法居多...

    http://xuewen.cnki.net/DownloadArticle.aspx?filename=BMKJ201104017&dbtype=CJFD <浅析基于DNS协议的隐蔽通 ...

  6. 机器学习经典分类算法 —— C4.5算法(附python实现代码)

    目录 理论介绍 什么是分类 分类的步骤 什么是决策树 决策树归纳 信息增益 相关理论基础 计算公式 ID3 C4.5 python实现 参考资料 理论介绍 什么是分类 分类属于机器学习中监督学习的一种 ...

  7. 15 分钟带你入门 sklearn 与机器学习(分类算法篇)

    众所周知,Scikit-learn(以前称为scikits.learn)是一个用于Python编程语言的免费软件机器学习库.它具有各种分类,回归和聚类算法,包括支持向量机,随机森林,梯度增强,k-me ...

  8. Sklearn 损失函数如何应用到_15 分钟带你入门 sklearn 与机器学习(分类算法篇)...

    众所周知,Scikit-learn(以前称为scikits.learn)是一个用于Python编程语言的免费软件机器学习库.它具有各种分类,回归和聚类算法,包括支持向量机,随机森林,梯度增强,k-me ...

  9. 【机器学习】分类算法-K-近邻算法

    目标 说明K-近邻算法的距离公式 说明K-近邻算法的超参数K值以及取值问题 说明K-近邻算法的优缺点 应用KNeighborsClassifier实现分类 了解分类算法的评估标准准确率 应用:Face ...

最新文章

  1. 建设有竞争力的APP开发团队
  2. 艾特某人代码实现_为何敲代码,学好数学很重要?
  3. Tensorflow 错误总结:ImportError: cannot import name add_newdocs.
  4. leetcode 213. House Robber II | 213. 打家劫舍 II(Java)
  5. 使用Keras和TensorFlow构建深度自动编码器
  6. MATLAB中的微积分运算(数值符号)
  7. python--爬虫01
  8. java mp4转码 h264_10分钟学会Jave视频转码avi--gt;mp4(h264编码格式)!_Java_七九推...
  9. (重读)JavaScript高级程序设计第四版
  10. GD32F103快速替换STM32F103
  11. 玩转 ESP32 + Arduino (十八) 采用SIM800L发送短信和定位(基础知识)
  12. delete语句详解
  13. 【Linux服务器架设】搭建存储服务器-NFS
  14. 卡片跳转快应用指定页面,如何点返回直接退出快应用回到卡片
  15. 【高等代数】行列式的定义和性质
  16. 1148: 组合三位数之一 C语言
  17. 计算机图形学(一) 视频显示设备_2_光栅扫描显示器
  18. 使用C语言的七个步骤
  19. Java中如何保证线程安全性
  20. 【LINUX】Linux之Ubuntu系统安装搜狗输入法

热门文章

  1. 服务器主板信息花屏,黑屏花屏别慌 小诀窍帮你搞定常见问题
  2. 教你如何做好团购和团购推广
  3. 分布式和集群的区别和联系
  4. 昨天我开除了一名程序员,因为简历造假!
  5. ps cs5 gif 动画 分解
  6. nRF5340(入门篇)之1.1 nrf5340芯片简介
  7. mysql期末实验实训装置厂家_消防广播电话系统实验实训装置
  8. JVM原理优化及GC
  9. Python入门课程课件
  10. M5310A模组与onenet平台通信流程详解