opencv-python运用模板寻找黑白子,并计算出两类棋子各自最大距离,并用直线连接,用霍夫变换检测棋盘黑线,用直线画出

# 获取白子的模板
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()

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值