基于python定位棋子位置及识别棋子颜色


Posted in Python onJuly 26, 2021

这一篇主要实现定位棋子位置及识别棋子颜色。

围棋棋盘原图如下:

基于python定位棋子位置及识别棋子颜色

经过上一章节处理,已经将棋盘位置找到,如下图:

基于python定位棋子位置及识别棋子颜色

现在根据新图,进行棋子位置的定位

1、将棋盘分割成19x19的小方格

为了定位出棋盘每个交叉点上,是否有棋子,需要将棋盘分割成19X19的小方格,由于围棋棋盘每个交叉线直接距离相同,是矩形,因此分割成小方格十分容易,如下图:

基于python定位棋子位置及识别棋子颜色

若想将棋盘分割成19x19的小方格,需要知道以下几个参数。

small_length=38  #每个小格宽高
qizi_zhijing=38#棋子直径
zuoshangjiao=20#棋盘四周的宽度

这些可以使用imagewathch(VS下opencv的插件)工具,方便的知道,这个工具可以实时查看图像的宽高,某个位置的像素值。

下面是将原图分割成19X19小方格的代码

img = cv2.imread("src.jpg")
cv2.imshow("src",img)
#变量定义
small_length=38  #每个小格宽高
qizi_zhijing=38#棋子直径
zuoshangjiao=20#棋盘四周的宽度

for i in range(19):
    for j in range(19):
        #print(i,j)
        lie = i
        hang = j
        Tp_x = small_length * lie
        Tp_y = small_length * hang
        Tp_width = qizi_zhijing
        Tp_height = qizi_zhijing

        #测试用
        cv2.rectangle(img, (Tp_x, Tp_y), (Tp_x + Tp_width, Tp_y + Tp_height),(255, 0, 0), 2)
        cv2.imwrite('img.jpg', img)
        img_temp=img[Tp_y:Tp_y+Tp_height, Tp_x:Tp_x+Tp_width]#参数含义分别是:y、y+h、x、x+w
        cv2.imwrite('img_temp3.jpg', img_temp)
        cv2.imshow("3", img_temp)
        cv2.waitKey(20)

2、根据像素占比识别是否是黑色棋子

基于python定位棋子位置及识别棋子颜色
基于python定位棋子位置及识别棋子颜色
基于python定位棋子位置及识别棋子颜色

上面三种图像是我们分割成小方格后的三种主要形态,分别代表黑色棋子,白色棋子以及无棋子。其中黑色棋子最好查找,我们将图像进行灰度化——二值化后,通过统计黑色像素占比超过一定数值,就能知道该处是否有黑色棋子。

这里我将统计黑色占比的代码,封装成了一个函数,如下;

"""  "*******************************************************************************************
*函数功能 :统计二值化图片黑色像素点百分比
*输入参数 :输入裁剪后图像,
*返 回 值 :返回黑色像素点占比0-1之间
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def Heise_zhanbi(img):
    [height, width, tongdao] = img.shape
    #print(width, height, tongdao)
    # cv2.imshow("3", img)
    # cv2.waitKey(20)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.imshow("binary", gray)
    # cv2.waitKey(100)

    etVal, threshold = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY)
    # cv2.imshow("threshold", threshold)
    # cv2.waitKey(200)
    a = 0
    b = 0
    counter = 0#;/*目标像素点个数*/
    zhanbi = 0#;/*目标像素点比值*/
    for row in range(height):
        for col in range(width):
            val = threshold[row][col]
            if (val) == 0:#黑色
                a = a + 1
            else:
                b = b + 1
    zhanbi = (float)(a) / (float)(height*width)
    #print("黑色像素个数", a, "黑色像素占比", zhanbi)
    return zhanbi

3、根据像素占比识别是否是白色棋子

同样的,我们可以统计像素中白色占比,来进行识别该位置是否是白色棋子,但是这里需要注意一个问题,如果按照上面黑色棋子识别方法进行灰度化、二值化会造成白色棋子和无棋子分辨不了,二者都有大面积的白色,因此这里需要调整二值化的阈值,分开无棋子和白色棋子的图像。

封装好的代码如下:

"""  "*******************************************************************************************
*函数功能 :统计二值化图片白色像素点百分比
*输入参数 :输入裁剪后图像,
*返 回 值 :返回白色像素点占比0-1之间
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def Baise_zhanbi(img):
    [height, width, tongdao] = img.shape
    #print(width, height, tongdao)
    # cv2.imshow("3", img)
    # cv2.waitKey(20)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.imshow("binary", gray)
    # cv2.waitKey(100)

    etVal, threshold = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)
    # cv2.imshow("threshold", threshold)
    # cv2.waitKey(200)
    a = 0
    b = 0
    counter = 0#;/*目标像素点个数*/
    zhanbi = 0#;/*目标像素点比值*/
    for row in range(height):
        for col in range(width):
            val = threshold[row][col]
            if (val) == 0:#黑色
                a = a + 1
            else:
                b = b + 1
    zhanbi = (float)(b) / (float)(height*width)
    #print("白色像素个数", b, "白色像素占比", zhanbi)
    return zhanbi

效果图如下:

基于python定位棋子位置及识别棋子颜色

4、将棋盘棋子位置通过列表表示

我们新建一个19*19的列表来存储棋子,列表中:

0:代表无棋子
1:代表白色
2:代表黑色

代码如下:

list = [[0 for i in range(19)] for j in range(19)]

当为黑色棋子时:

list[hang][lie]=2#黑色
#print("当前棋子为黑色")
print("第", i, "行,第", j, "列棋子为黑色:", i, j)

当为白色棋子时:

list[hang][lie] = 1  # 白色
#print("当前棋子为白色")
print("第", i, "行,第", j, "列棋子为白色:", i, j)

效果图如下:

基于python定位棋子位置及识别棋子颜色

完整代码如下:

from PIL import ImageGrab
import numpy as np
import cv2
from glob import glob
import os

import time


#Python将数字转换成大写字母
def getChar(number):
    factor, moder = divmod(number, 26) # 26 字母个数
    modChar = chr(moder + 65)          # 65 -> 'A'
    if factor != 0:
        modChar = getChar(factor-1) + modChar # factor - 1 : 商为有效值时起始数为 1 而余数是 0
    return modChar
def getChars(length):
    return [getChar(index) for index in range(length)]



"""  "*******************************************************************************************
*函数功能 :统计二值化图片黑色像素点百分比
*输入参数 :输入裁剪后图像,
*返 回 值 :返回黑色像素点占比0-1之间
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def Heise_zhanbi(img):
    [height, width, tongdao] = img.shape
    #print(width, height, tongdao)
    # cv2.imshow("3", img)
    # cv2.waitKey(20)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.imshow("binary", gray)
    # cv2.waitKey(100)

    etVal, threshold = cv2.threshold(gray, 125, 255, cv2.THRESH_BINARY)
    # cv2.imshow("threshold", threshold)
    # cv2.waitKey(200)
    a = 0
    b = 0
    counter = 0#;/*目标像素点个数*/
    zhanbi = 0#;/*目标像素点比值*/
    for row in range(height):
        for col in range(width):
            val = threshold[row][col]
            if (val) == 0:#黑色
                a = a + 1
            else:
                b = b + 1
    zhanbi = (float)(a) / (float)(height*width)
    #print("黑色像素个数", a, "黑色像素占比", zhanbi)
    return zhanbi


"""  "*******************************************************************************************
*函数功能 :统计二值化图片白色像素点百分比
*输入参数 :输入裁剪后图像,
*返 回 值 :返回白色像素点占比0-1之间
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def Baise_zhanbi(img):
    [height, width, tongdao] = img.shape
    #print(width, height, tongdao)
    # cv2.imshow("3", img)
    # cv2.waitKey(20)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.imshow("binary", gray)
    # cv2.waitKey(100)

    etVal, threshold = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)
    # cv2.imshow("threshold", threshold)
    # cv2.waitKey(200)
    a = 0
    b = 0
    counter = 0#;/*目标像素点个数*/
    zhanbi = 0#;/*目标像素点比值*/
    for row in range(height):
        for col in range(width):
            val = threshold[row][col]
            if (val) == 0:#黑色
                a = a + 1
            else:
                b = b + 1
    zhanbi = (float)(b) / (float)(height*width)
    #print("白色像素个数", b, "白色像素占比", zhanbi)
    return zhanbi

"""  "*******************************************************************************************
*函数功能 :定位棋盘位置
*输入参数 :截图
*返 回 值 :裁剪后的图像
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def dingweiqizi_weizhi(img):
    '''********************************************
    1、定位棋盘位置
    ********************************************'''
    #img = cv2.imread("./screen/1.jpg")

    image = img.copy()
    w, h, c = img.shape
    img2 = np.zeros((w, h, c), np.uint8)
    img3 = np.zeros((w, h, c), np.uint8)
    # img = ImageGrab.grab() #bbox specifies specific region (bbox= x,y,width,height *starts top-left)

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower = np.array([10, 0, 0])
    upper = np.array([40, 255, 255])
    mask = cv2.inRange(hsv, lower, upper)
    erodeim = cv2.erode(mask, None, iterations=2)  # 腐蚀
    dilateim = cv2.dilate(erodeim, None, iterations=2)

    img = cv2.bitwise_and(img, img, mask=dilateim)
    frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, dst = cv2.threshold(frame, 100, 255, cv2.THRESH_BINARY)
    contours, hierarchy = cv2.findContours(dst, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)



    #cv2.imshow("0", img)

    i = 0
    maxarea = 0
    nextarea = 0
    maxint = 0
    for c in contours:
        if cv2.contourArea(c) > maxarea:
            maxarea = cv2.contourArea(c)
            maxint = i
        i += 1

    # 多边形拟合
    epsilon = 0.02 * cv2.arcLength(contours[maxint], True)
    if epsilon < 1:
        print("error :   epsilon < 1")
        pass

    # 多边形拟合
    approx = cv2.approxPolyDP(contours[maxint], epsilon, True)
    [[x1, y1]] = approx[0]
    [[x2, y2]] = approx[2]

    checkerboard = image[y1:y2, x1:x2]
    # cv2.imshow("1", checkerboard)
    # cv2.waitKey(1000)
    #cv2.destroyAllWindows()
    return checkerboard

"""  "*******************************************************************************************
*函数功能 :定位棋子颜色及位置
*输入参数 :裁剪后的图像
*返 回 值 :棋子颜色及位置列表
*编写时间 : 2021.6.30
*作    者 : diyun
********************************************************************************************"""
def dingweiqizi_yanse_weizhi(img):
    '''********************************************
    2、识别棋盘棋子位置及颜色及序号;
    ********************************************'''
    #img = cv2.imread("./checkerboard/checkerboard_1.jpg")
    img = cv2.resize(img, (724,724), interpolation=cv2.INTER_AREA)
    #cv2.imshow("src",img)
    #cv2.waitKey(1000)

    #变量定义
    small_length=38  #每个小格宽高
    qizi_zhijing=38#棋子直径
    zuoshangjiao=20#棋盘四周的宽度

    list = [[0 for i in range(19)] for j in range(19)]
    #print(list)

    for i in range(19):
        for j in range(19):

            lie = i
            hang = j

            Tp_x = small_length * lie
            Tp_y = small_length * hang
            Tp_width = qizi_zhijing
            Tp_height = qizi_zhijing

            img_temp=img[Tp_y:Tp_y+Tp_height, Tp_x:Tp_x+Tp_width]#参数含义分别是:y、y+h、x、x+w

            heise_zhanbi=Heise_zhanbi(img_temp)
            if heise_zhanbi>0.5:
                list[hang][lie]=2#黑色
                print("第", j+1, "行,第", i+1, "列棋子为黑色")
                #print("当前棋子为黑色")
            else:
                baise_zhanbi = Baise_zhanbi(img_temp)
                if baise_zhanbi > 0.15:
                    list[hang][lie] = 1  # 白色
                    print("第", j+1, "行,第",i+1 , "列棋子为白色")
                    #print("当前棋子为白色")
                else:
                    list[hang][lie] = 0  # 无棋子
                    #print("当前位置没有棋子")
            #print(heise_zhanbi)
    #cv2.imshow("2",img)
    #print("\n")
    #print(list)
    return  list



if __name__ =="__main__":
    list0 = [[0 for i in range(19)] for j in range(19)]
    list_finall = []
    img = cv2.imread("./screen/9.jpg")

    '''********************************************
    1、定位棋盘位置
    ********************************************'''
    img_after=dingweiqizi_weizhi(img)
    #cv2.imshow("src",img)

    '''********************************************
    2、识别棋盘棋子位置及颜色及序号;
    ********************************************'''
    list1=dingweiqizi_yanse_weizhi(img_after)
    print(list1)

到此这篇关于基于python定位棋子位置及识别棋子颜色的文章就介绍到这了,更多相关python定位棋子位置及识别棋子颜色内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python求素数示例分享
Feb 16 Python
Python实现基于HTTP文件传输实例
Nov 08 Python
利用python爬取散文网的文章实例教程
Jun 18 Python
Python 记录日志的灵活性和可配置性介绍
Feb 27 Python
使用pycharm生成代码模板的实例
May 23 Python
深度辨析Python的eval()与exec()的方法
Mar 26 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
Aug 07 Python
python中的 zip函数详解及用法举例
Feb 16 Python
pycharm中import呈现灰色原因的解决方法
Mar 04 Python
详解用python -m http.server搭一个简易的本地局域网
Sep 24 Python
基于django和dropzone.js实现上传文件
Nov 24 Python
Python基础之元组与文件知识总结
May 19 Python
Python 处理表格进行成绩排序的操作代码
python识别围棋定位棋盘位置
python之基数排序的实现
Jul 26 #Python
python之PySide2安装使用及QT Designer UI设计案例教程
python代码实现备忘录案例讲解
Jul 26 #Python
python之django路由和视图案例教程
Jul 26 #Python
OpenCV图像变换之傅里叶变换的一些应用
You might like
如何获得PHP相关资料
2006/10/09 PHP
PHP函数strip_tags的一个bug浅析
2014/05/22 PHP
php计算两个坐标(经度,纬度)之间距离的方法
2015/04/17 PHP
PHP人民币金额转大写实例代码
2015/10/02 PHP
PHP CURL与java http使用方法详解
2018/01/26 PHP
如何通过PHP实现Des加密算法代码实例
2020/05/09 PHP
THINKPHP5.1 Config的配置与获取详解
2020/06/08 PHP
javascript操作cookie的文章(设置,删除cookies)
2010/04/01 Javascript
jquery判断元素是否隐藏的多种方法
2014/05/06 Javascript
BootStrap实现轮播图效果(收藏)
2016/12/30 Javascript
javascript循环链表之约瑟夫环的实现方法
2017/01/16 Javascript
vue.js中mint-ui框架的使用方法
2017/05/12 Javascript
vue+jquery+lodash实现滑动时顶部悬浮固定效果
2018/04/28 jQuery
nodejs 使用 js 模块的方法实例详解
2018/12/04 NodeJs
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
详解实现一个通用的“划词高亮”在线笔记功能
2019/04/23 Javascript
JavaScript中callee和caller的区别与用法实例分析
2019/06/28 Javascript
React 条件渲染最佳实践小结(7种)
2020/09/27 Javascript
Python实现文件复制删除
2016/04/19 Python
Python 实现「食行生鲜」签到领积分功能
2018/09/26 Python
Python设计模式之备忘录模式原理与用法详解
2019/01/15 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
python代码 FTP备份交换机配置脚本实例解析
2019/08/01 Python
TensorFlow 显存使用机制详解
2020/02/03 Python
python实现PCA降维的示例详解
2020/02/24 Python
python怎么调用自己的函数
2020/07/01 Python
python实现每天自动签到领积分的示例代码
2020/08/18 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
html5触摸事件判断滑动方向的实现
2018/06/05 HTML / CSS
Html5移动端网页端适配(js+rem)
2021/02/03 HTML / CSS
德国排名第一的主题公园门票网站:Attraction Tickets Direct
2019/09/09 全球购物
教师产假请假条范文
2014/04/10 职场文书
校园广播稿100字
2014/10/06 职场文书
债务纠纷委托书范本
2014/10/14 职场文书
三八节活动主持词
2015/07/04 职场文书
python实现简单的井字棋
2021/05/26 Python