python识别围棋定位棋盘位置

1. 前言

围棋是一种源远流长的中华民族文化遗产,它在中国有着广泛的爱好者和玩家。如今,随着人工智能的发展,围棋AI技术也日趋成熟,AlphaGo 更是在围棋领域引起巨大的反响。本文介绍一种 Python 识别围棋并定位棋盘位置的方法。

2. 相关技术

2.1 OpenCV

作为一种基于 BSD 许可(开源)发行的计算机视觉和机器学习软件库,OpenCV 可以轻松地进行如人脸识别、物体识别、车牌识别等计算机视觉和模式识别任务。

在本文中,OpenCV 可以帮助我们完成对围棋棋盘的识别和定位。

2.2 Convnets 神经网络

卷积神经网络是当前计算机视觉领域最为流行的深度学习模型之一。它被广泛应用于图像处理、自然语言处理、视频分析等领域。

在本文中,我们将使用一种基于卷积神经网络的算法来识别围棋棋盘。

3. Python 识别围棋

3.1 安装 OpenCV

在使用 OpenCV 进行图像处理之前,我们需要先安装该库。

!pip install opencv-python

3.2 加载图像

我们需要从本地加载需要识别的围棋棋盘图像,比如下面这张:

可以使用 OpenCV 的 imread() 函数从本地加载图像:

import cv2

img = cv2.imread("weiqi_board.jpg", 0)

cv2.imshow("image", img)

cv2.waitKey(0)

cv2.destroyAllWindows()

在上述代码中,cv2.imread() 函数将图像转换为黑白模式,因为黑白模式的图像对于后续处理更容易。

3.3 图像处理

在获取了围棋棋盘的图像后,我们将对图像进行如下处理:

使用高斯滤波去除噪点。

使用 Canny 算法进行边缘检测。

对边缘图像进行膨胀操作,以填补空隙。

import numpy as np

# 高斯模糊去噪

img_blur = cv2.GaussianBlur(img, (5, 5), 0)

# Canny 边缘检测

edges = cv2.Canny(img_blur, 50, 150, apertureSize=3)

# 膨胀操作

kernel = np.ones((3,3), np.uint8)

dilation = cv2.dilate(edges, kernel, iterations=1)

cv2.imshow("image", dilation)

cv2.waitKey(0)

cv2.destroyAllWindows()

处理后的结果如下图所示:

3.4 轮廓检测和逼近多边形

在膨胀处理后的边缘图像中,我们需要检测并逼近出围棋棋盘的轮廓。

_, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

image_contours = cv2.drawContours(img, contours, -1, (0,255,0), 3)

# 查找面积最大的轮廓

max_contour = max(contours, key=cv2.contourArea)

image_max_contour = cv2.drawContours(img.copy(), [max_contour], 0, (0,0,255), 3)

epsilon = 0.05 * cv2.arcLength(max_contour,True)

approx = cv2.approxPolyDP(max_contour, epsilon, True)

image_approx = cv2.drawContours(img.copy(), [approx], 0, (0,0,255), 3)

cv2.imshow("image_contours", image_contours)

cv2.imshow("image_max_contour", image_max_contour)

cv2.imshow("image_approx", image_approx)

cv2.waitKey(0)

cv2.destroyAllWindows()

上述代码中,我们使用 findContours() 函数查找边缘,并使用 drawContours() 函数将其绘制出来。然后我们查找面积最大的轮廓,并使用 approxPolyDP() 函数对轮廓进行逼近处理,得到一个六边形的多边形。

执行结果如下图所示:

3.5 透视变换

在得到了围棋棋盘的多边形后,我们需要使用透视变换将其变形为矩形,接下来,我们就可以通过透视变换的变换矩阵,将图像映射为一个标准的矩形图像。同时,为了得到一盘定位准确的围棋棋盘,需要将定位框扩大一定的范围。

def perspective_transform(corners, img):

rows,cols,ch = img.shape

# 对角点按顺序排列

corners = corners[np.argsort(corners.reshape(-1, 2).sum(axis=1))]

# 定义目标变换后图像大小

width = max(np.sqrt(((corners[3] - corners[0]) ** 2).sum()),

np.sqrt(((corners[2] - corners[1]) ** 2).sum()))

height = max(np.sqrt(((corners[1] - corners[0]) ** 2).sum()),

np.sqrt(((corners[2] - corners[3]) ** 2).sum()))

dst = np.array([[0, 0],

[0, height - 1],

[width - 1, height - 1],

[width - 1, 0]], dtype=np.float32)

# 求变换矩阵

M = cv2.getPerspectiveTransform(corners, dst)

# 执行透视变换

return cv2.warpPerspective(img, M, (int(width), int(height)))

pts = np.array([

[approx[0][0][0], approx[0][0][1]],

[approx[1][0][0], approx[1][0][1]],

[approx[2][0][0], approx[2][0][1]],

[approx[3][0][0], approx[3][0][1]]

])

img_perspective = perspective_transform(pts, img)

cv2.imshow("perspective_transform", img_perspective)

cv2.waitKey(0)

cv2.destroyAllWindows()

处理后的结果,如下图所示:

3.6 参考代码

import cv2

import numpy as np

def perspective_transform(corners, img):

rows,cols,ch = img.shape

# 对角点按顺序排列

corners = corners[np.argsort(corners.reshape(-1, 2).sum(axis=1))]

# 定义目标变换后图像大小

width = max(np.sqrt(((corners[3] - corners[0]) ** 2).sum()),

np.sqrt(((corners[2] - corners[1]) ** 2).sum()))

height = max(np.sqrt(((corners[1] - corners[0]) ** 2).sum()),

np.sqrt(((corners[2] - corners[3]) ** 2).sum()))

dst = np.array([[0, 0],

[0, height - 1],

[width - 1, height - 1],

[width - 1, 0]], dtype=np.float32)

# 求变换矩阵

M = cv2.getPerspectiveTransform(corners, dst)

# 执行透视变换

return cv2.warpPerspective(img, M, (int(width), int(height)))

# 加载图片

img = cv2.imread("weiqi_board.jpg",0)

# 高斯模糊去噪

img_blur = cv2.GaussianBlur(img, (5, 5), 0)

# Canny 边缘检测

edges = cv2.Canny(img_blur, 50, 150, apertureSize=3)

# 膨胀操作

kernel = np.ones((3,3), np.uint8)

dilation = cv2.dilate(edges, kernel, iterations=1)

# 进行轮廓检测和多边形逼近

_, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

max_contour = max(contours, key=cv2.contourArea)

epsilon = 0.05 * cv2.arcLength(max_contour,True)

approx = cv2.approxPolyDP(max_contour, epsilon, True)

pts = np.array([

[approx[0][0][0], approx[0][0][1]],

[approx[1][0][0], approx[1][0][1]],

[approx[2][0][0], approx[2][0][1]],

[approx[3][0][0], approx[3][0][1]]

])

# 执行透视变换

img_perspective = perspective_transform(pts, img)

# 显示处理后的图像

cv2.imshow("image_perspective", img_perspective)

cv2.waitKey(0)

cv2.destroyAllWindows()

4. 总结

到这里,我们就可以通过 Python 识别围棋并定位棋盘位置了。本文介绍了使用 OpenCV 进行图像处理,使用卷积神经网络进行围棋棋盘的识别与定位,使用透视变换将棋盘透视成矩形。通过学习本文,相信大家对 Python 的图像处理和围棋AI技术有了更深入的了解。

后端开发标签