# 获取白子的模板
template = cv2.imread('white.jpg', 0)
w, h = template.shape[::-1]
# 获取黑子的模板
template2 = cv2.imread('black.jpg', 0)
w2, h2 = template2.shape[::-1]
上述代码用于获取棋子的模板,模板操作输入的图片应是二值化格式的图片
# 模板匹配
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
res2 = cv2.matchTemplate(img_gray, template2, cv2.TM_CCOEFF_NORMED)
上述代码进行模板匹配
# 用于存储黑白子的中心位置
point1 = []
point2 = []
# 将按照模板找到的棋子进行画圈处理
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)
if len(point1) == 0:
point1.append((pt[0] + w / 2, pt[1] + h / 2))
elif check((pt[0] + w / 2, pt[1] + h / 2), point1):
point1.append((pt[0] + w / 2, pt[1] + h / 2))
for pt in zip(*loc2[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w2, pt[1] + h2), (0, 255, 0), 1)
if len(point2) == 0:
point2.append((pt[0] + w2 / 2, pt[1] + h2 / 2))
elif check((pt[0] + w2 / 2, pt[1] + h2 / 2), point2):
point2.append((pt[0] + w2 / 2, pt[1] + h2 / 2))
上述代码用于存储黑白棋子的中心位置,通过列表将棋子的中心记录下来,用不同颜色的框将黑白子区分出来
cnt = 0 # for循环计步
# 寻找两个棋子之间的最大距离,并将两个棋子记录下来
for i in point1[cnt:-1]:
for j in point1[cnt + 1:]:
distance = calculate(i, j)
if (distance > max1):
max1 = distance
maxPoint1.clear()
maxPoint1.append(i)
maxPoint1.append(j)
cnt += 1
cnt = 0
for i in point2[cnt:-1]:
for j in point2[cnt+1:]:
distance = calculate(i, j)
if (distance > max2):
max2 = distance
maxPoint2.clear()
maxPoint2.append(i)
maxPoint2.append(j)
cnt += 1
上述代码用于记录运算两个棋子之间的距离,将最大距离保存下来,最终将两个棋子用线连接起来
point_11 = (int(maxPoint1[0][0]), int(maxPoint1[0][1]))
point_12 = (int(maxPoint1[1][0]), int(maxPoint1[1][1]))
point_21 = (int(maxPoint2[0][0]), int(maxPoint2[0][1]))
point_22 = (int(maxPoint2[1][0]), int(maxPoint2[1][1]))
cv2.line(img_rgb, point_11, point_12, (0, 0, 255), 2)
cv2.line(img_rgb, point_21, point_22, (0, 255, 0), 2)
上述代码用于在找到的棋子记录下并连线
# 边缘检测,将边缘描红
edges = cv2.Canny(img_gray, 126, 255, apertureSize=3)
minLineLength = 5
maxLineGap = 1
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100,
minLineLength, maxLineGap)
# 将整个棋盘按边缘描红
for line in lines:
x1 = line[0][0]
y1 = line[0][1]
x2 = line[0][2]
y2 = line[0][3]
cv2.line(img_rgb, (x1, y1), (x2, y2), (0, 255, 255), 2)
上诉代码用边缘检测找到棋盘的每条线,用霍夫变换检测直线,并将直线在图中画出
原图(代码中用到的素材):
结果截图:
完整代码:
import cv2
import numpy as np
# 用于计算两点之间的距离,便于后面寻找最大值和划线
def calculate(newpoint, oldpoint):
p1 = np.array([newpoint[0], newpoint[1]])
p2 = np.array([oldpoint[0], oldpoint[1]])
distance = np.linalg.norm(p1 - p2)
return distance
def check(point, points_list):
if (point[0] - points_list[-1][0]) > 5 or (point[1] - points_list[-1][1]) > 5:
return True
return False
img_rgb = cv2.imread('qipan.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
# 获取白子的模板
template = cv2.imread('white.jpg', 0)
w, h = template.shape[::-1]
# 获取黑子的模板
template2 = cv2.imread('black.jpg', 0)
w2, h2 = template2.shape[::-1]
# 模板匹配
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
res2 = cv2.matchTemplate(img_gray, template2, cv2.TM_CCOEFF_NORMED)
# 找到像素的地址
threshold = 0.7
loc = np.where(res >= threshold)
loc2 = np.where(res2 >= threshold)
# 用于存储黑白子的中心位置
point1 = []
point2 = []
# 将按照模板找到的棋子进行画圈处理
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)
if len(point1) == 0:
point1.append((pt[0] + w / 2, pt[1] + h / 2))
elif check((pt[0] + w / 2, pt[1] + h / 2), point1):
point1.append((pt[0] + w / 2, pt[1] + h / 2))
for pt in zip(*loc2[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w2, pt[1] + h2), (0, 255, 0), 1)
if len(point2) == 0:
point2.append((pt[0] + w2 / 2, pt[1] + h2 / 2))
elif check((pt[0] + w2 / 2, pt[1] + h2 / 2), point2):
point2.append((pt[0] + w2 / 2, pt[1] + h2 / 2))
# 记录棋子的最大距离
max1 = 0
max2 = 0
# 存储黑或白子之间最大的距离
maxPoint1 = []
maxPoint2 = []
cnt = 0 # for循环计步
# 寻找两个棋子之间的最大距离,并将两个棋子记录下来
for i in point1[cnt:-1]:
for j in point1[cnt + 1:]:
distance = calculate(i, j)
if (distance > max1):
max1 = distance
maxPoint1.clear()
maxPoint1.append(i)
maxPoint1.append(j)
cnt += 1
cnt = 0
for i in point2[cnt:-1]:
for j in point2[cnt+1:]:
distance = calculate(i, j)
if (distance > max2):
max2 = distance
maxPoint2.clear()
maxPoint2.append(i)
maxPoint2.append(j)
cnt += 1
point_11 = (int(maxPoint1[0][0]), int(maxPoint1[0][1]))
point_12 = (int(maxPoint1[1][0]), int(maxPoint1[1][1]))
point_21 = (int(maxPoint2[0][0]), int(maxPoint2[0][1]))
point_22 = (int(maxPoint2[1][0]), int(maxPoint2[1][1]))
cv2.line(img_rgb, point_11, point_12, (0, 0, 255), 2)
cv2.line(img_rgb, point_21, point_22, (0, 255, 0), 2)
# 边缘检测,将边缘描红
edges = cv2.Canny(img_gray, 126, 255, apertureSize=3)
minLineLength = 5
maxLineGap = 1
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100,
minLineLength, maxLineGap)
# 将整个棋盘按边缘描红
for line in lines:
x1 = line[0][0]
y1 = line[0][1]
x2 = line[0][2]
y2 = line[0][3]
cv2.line(img_rgb, (x1, y1), (x2, y2), (0, 255, 255), 2)
cv2.namedWindow('white', cv2.WINDOW_NORMAL)
cv2.imshow('white', img_rgb)
c = cv2.waitKey(0)
cv2.destroyAllWindows()