新闻动态

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

发布日期:2022-02-21 15:28 | 文章来源:脚本之家

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

围棋棋盘原图如下:


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


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

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

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


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

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

这些可以使用imagewathch(VS下opencv的插件)工具,方便的知道,这个工具可以实时查看图像的宽高,某个位置的像素值。这个工具的使用可以看我另外一篇文章:opencv用VS2013调试时用Image Watch插件查看图片,代替一堆数据,直观很多。
下面是将原图分割成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、根据像素占比识别是否是黑色棋子




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

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

"""  "*******************************************************************************************
*函数功能 :统计二值化图片黑色像素点百分比
*输入参数 :输入裁剪后图像,
*返 回 值 :返回黑色像素点占比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

效果图如下:

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)

效果图如下:

完整代码如下:

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定位棋子位置及识别棋子颜色内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

香港服务器租用

版权声明:本站文章来源标注为YINGSOO的内容版权均为本站所有,欢迎引用、转载,请保持原文完整并注明来源及原文链接。禁止复制或仿造本网站,禁止在非www.yingsoo.com所属的服务器上建立镜像,否则将依法追究法律责任。本站部分内容来源于网友推荐、互联网收集整理而来,仅供学习参考,不代表本站立场,如有内容涉嫌侵权,请联系alex-e#qq.com处理。

相关文章

实时开通

自选配置、实时开通

免备案

全球线路精选!

全天候客户服务

7x24全年不间断在线

专属顾问服务

1对1客户咨询顾问

在线
客服

在线客服:7*24小时在线

客服
热线

400-630-3752
7*24小时客服服务热线

关注
微信

关注官方微信
顶部