相关文章推荐
听话的牛腩  ·  ASP.NET Core MVC 项目 ...·  7 月前    · 
知识渊博的蟠桃  ·  Spring - ...·  1 年前    · 
逃课的小虾米  ·  python ...·  1 年前    · 

1. 前言

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

2. 图像的矩特征

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

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

import cv2
import numpy as np
def 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 np
def humoments(img_gray, log=True):
    """返回图像7个不变矩"""
    hu = cv2.HuMoments(cv2.moments(img_gray))[:,0]
    if log:
        hu = np.log(np.abs(hu))
    return hu
def jitter(im_cv, theta):
    """随机旋转和抖动,返回新的图像"""
    #theta = np.random.random()*360
    dx, dy = np.random.randint(0, 5, 2) - 2
    im_pil = Image.fromarray(im_cv)
    im_pil = im_pil.rotate(theta, translate=(dx, dy))
    im = np.array(im_pil)
    im[im==0] = 240
    im = np.where(im>128, 240, 15).astype(np.uint8)
    return im
if __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] = True
    target = 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] = 240
            piece = 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 RandomForestClassifier
ds = 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.9994213
 0.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]]]
['象', '象', '象', '象', '象', '象', '象', '象', '象', '象']
['卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒', '卒']
['车', '车', '车', '车', '车', '车', '车', '士', '车', '车']
['马', '马', '马', '马', '炮', '马', '马', '马', '马', '马']
['相', '相', '相', '相', '相', '相', '相', '相', '相', '相']
['士', '士', '士', '士', '士', '士', '士', '士', '士', '士']
['将', '将', '将', '将', '将', '将', '将', '将', '将', '将']
['帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅', '帅']
['兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵', '兵']
['炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮', '炮']
                    文本识别早已经不是问题了,不过却不能直接应用于象棋棋子的识别,因为棋盘上的棋子是随机摆放上去的,不能保证棋子上的文字总是保持一个固定的角度。识别棋子的关键是找到具有“旋转不变性”的特征——无论棋子旋转多少度,其特征总是稳定的。
数据集介绍
本篇博客采用的数据集是中国象棋棋子数据集,包含十种棋子分别是帅、仕、象、马、炮、车、兵、卒、将、相。
每个分好类的文件夹里有719张128x128像素的图片,形状一样,但是旋转角度不同数据来源,和鲸社区开放数据集,可以点击下面链接获取中国象棋棋子数据集
数据集截图如下:
数据预处理
卷积神经网络
什么是卷积神经网络
本篇博客用到的
				
Speeded Up Robust Features(SURF,加速稳健特征),是一种稳健的局部特征点检测和描述算法。Surf是对David Lowe在1999年提出的Sift算法的改进,提升了算法的执行效率,为算法在实时计算机视觉系统中应用提供了可能。Sift算法一样,Surf算法的基本路程可以分为三大部分:局部特征点的提取、特征点的描述、特征点的匹配。详细介绍可参考以下网页: Surf算法特征点检测与匹配 本项目的要求如下: 通过摄像头捕捉获取到的每帧图像进行处理。将多个象棋棋子摆在桌 子...
本人机对弈程序采用了多种搜索算法.以下是本程序主要的类说明: 1.CEveluation类:估值类,对给定的棋盘进行估值. 2.CMoveGenerator类:走法产生器,对给定的棋盘局面搜索出所有可能的走法. 3.CSearchEngine类:搜索引擎基类. 4.CNegaMaxEngine类:负极大值法搜索引擎. 5.CAlphaBetaEngine类:采用了Alpha-Beta剪枝技术的搜索引擎. 6.CFAlphaBetaEngine类:fail-softalpha-beta搜索引擎. 7.CHistoryHeuristic类:历史启发类. 8.CAlphabeta_HHEngine类:带历史启发的Alpha-Beta搜索引擎. 9.CAspirationSearch类:渴望搜索引擎. 10.CIDAlphabetaEngine类:迭代深化搜索引擎. 11.CMTD_fEngine类:MTD(f)搜索引擎. 12.CTranspositionTable类:置换表. 13.CAlphaBeta_TTEngine类:加置换表的Alpha-Beta搜索引擎. 14.CPVS_Engine类:极小窗口搜索引擎. 15.CNegaScout_TT_HH类:使用了置换表和历史启发的NegaScout搜索引擎. 本程序还具有悔棋,还原功能,还可以记录走法. 注:本程序编写时参考了王小春的<>,他的书真是好.
基于opencv实现象棋识别及棋谱定位python源码+数据集(含代码注释)人工智能课程设计.zip 基于opencv实现象棋识别及棋谱定位python源码+数据集(含代码注释)人工智能课程设计.zip基于opencv实现象棋识别及棋谱定位python源码+数据集(含代码注释)人工智能课程设计.zip 【备注】主要针对正在做毕设的同学和需要项目实战的深度学习cv图像识别模式识别方向学习者。 也可作为课程设计、期末大作业。包含:项目源码,该项目可直接作为毕设使用。 也可以用来学习、参考、借鉴。如果基础不错,在此代码上做修改。
本文来自于网络,文章详细介绍了使用Python实现机器学习算法的损失函数、反向传播过程等相关知识。在这一章节里,我们将实现一个简单的神经网络架构,将2维的输入向量映射成二进制输出值。我们的神经网络有2个输入神经元,含6个隐藏神经元隐藏层及1个输出神经元。我们将通过层之间的权重矩阵来表示神经网络结构。在下面的例子中,输入层和隐藏层之间的权重矩阵将被表示为W,隐藏层和输出层之间的权重矩阵为W。除了连接神经元的权重向量外,每个隐藏和输出的神经元都会有一个大小为1的偏置量。我们的训练集由m=750个样本组成。因此,我们的矩阵维度如下:训练集维度:X=(750,2)目标维度:Y=(750,1)W维度:(
前言:自AlphaGo战胜世界著名九段围棋手李世石之后,我就对棋类人工智能产生了极大的兴趣,并想要自己实现象棋人工智能。然而那个时候我还在读高二,没有这么深厚的代码基础,所以那个时候也就只能想想了。但是现在不一样了,通过学习编程,已经可以让我在棋类人工智能这个领域向前探索了。 首先说明一下本系列博客描述的人工智能算法不是基于机器学习、深度学习这么高深的知识,而是一种穷举找最优走法的算法。之所以...
6.参考文献 Note: The above outline is a general structure for a paper on machine learning classification and should be adjusted to suit the specific details of your research. Also, in writing a research paper, It is also important to follow academic writing conventions and guidelines, such as formatting, referencing, citation. [code=plain] files_created: [] files_deleted: ['D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\CURRENT', 'D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\LOG.old', 'D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\MANIFEST-000001', 'D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\LOCK', 'D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\LOG', 'D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage\\000003.log'] files_modified: [] files_moved: [] dirs_modified: ['D:\\CodeDemo\\PythonProject\\SyncServer\\folder'] dirs_moved: [] dirs_deleted: ['D:\\CodeDemo\\PythonProject\\SyncServer\\folder\\Session Storage'] dirs_created: [] [/code]
B型超声设备图像处理:用二维数据生成扇形图像 Adair888: 你好,反过来怎么做呀。也想求问一下 B型超声设备图像处理:用二维数据生成扇形图像 Adair888: 想问下怎么做呀,急!谢谢 写给 python 程序员的 OpenGL 教程 zsh201215: 作者我想问一下 这个为什么报错[code=plain] Traceback (most recent call last): File "/home/<name>/pyopenglxiangmu/1.py", line 49, in <module> glutDisplayFunc(draw) # 3. 注册回调函数draw() File "/home/<name>/.local/lib/python3.10/site-packages/OpenGL/GLUT/special.py", line 147, in __call__ contextdata.setValue( self.CONTEXT_DATA_KEY, cCallback ) File "/home/<name>/.local/lib/python3.10/site-packages/OpenGL/contextdata.py", line 58, in setValue context = getContext( context ) File "/home/<name>/.local/lib/python3.10/site-packages/OpenGL/contextdata.py", line 40, in getContext raise error.Error( OpenGL.error.Error: Attempt to retrieve context when no valid context [/code] wxPython:一曲MFC时代的挽歌,更是理想主义的绝唱 不会pytho的小废废: mfc可以发吗作者表情包表情包表情包求啦