0%

【OpenCv】检测黑白棋

# 环境

  • Python 3.8.8
  • Pycharm 2021
  • opencv-Python

效果

在这里插入图片描述

基本原理

圆检测的原理是在直线检测原理上的拓展,可以先看看我这篇博客霍夫直线检测下面介绍圆检测的不同之处。
圆的表达式如下:

其中$a$和$b$表示圆心坐标,$r$表示圆半径,因此标准佛如霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆检测,此时效率就会很低,所以$OpenCv$中使用 霍夫梯度 进行圆形的检测。霍夫梯度法将圆检测分成两个阶段,第一阶段是检测圆心,第二段是利用圆心推导出圆半径,公式如下:

  • 圆心检测的原理:圆心是圆周角法线的交汇处,设置一个阈值,在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。
    在这里插入图片描述
  • 圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量打于该阈值,就认为该距离是该圆心的半径。

API

HoughCircles(image, method, dp, minDist,param1=100, param2=100, minRadius=0, maxRadius=0 )

  • method: CV_HOUGH_GRADENT
  • dp:累加面分辨率(大小) = 原始图像分辨率(大小) × 1 / dp。默认 dp = 1 时,两者分辨率相同。
  • minDist: 两个圆心的最小距离。若两圆心距离 < minDist,则认为是同一个圆
  • param1: canny边缘检测高阈值, 低限阈值是这个值的一半。越大检测圆边界时,要求的亮度梯度越大,一些灰灰的不明显的边界就会略去。
  • param2:累加平面某点是否是圆心的判定阈值。越小,越多假的圆会被检测到,越大,能通过检测的圆就更接近完美的圆形,默认为 100。
  • 后两个参数:允许检测到的圆的最大和最小半径。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import cv2 as cv
import numpy as np
import copy

#黑白棋子用不同颜色进行检测
def circle_detect() :
img = cv.imread('images/weiqi.png')
cimg = copy.deepcopy(img)
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# img_gray = cv.GaussianBlur(img_gray, (5, 5), 0)
#降噪
img_gray = cv.medianBlur(img_gray, 5)
circles = cv.HoughCircles(img_gray, cv.HOUGH_GRADIENT, 1, 10, param1 = 120, param2 = 50).squeeze()

for circle in circles :
#转成np.uint16数据类型扩大数据范围
circle = np.uint16(np.around(circle))
#做二值化处理,白棋为白,黑棋为黑,若圆心的值为255则为白棋,否则为黑棋
_, img_thresh = cv.threshold(img_gray, 80, 255, cv.THRESH_BINARY)
#注意x和y与w和h的对应
if img_thresh[circle[1], circle[0]] == 255 :
print(f'chess is black!')
# 画出检测到的圆
cv.circle(img, center=(circle[0], circle[1]), radius=circle[2],
color=(255, 0, 0), thickness=2)
# 画出圆心
cv.circle(img, center=(circle[0], circle[1]), radius=2,
color=(255, 0, 0), thickness=3)
else :
print('chess is white!')
# 画出检测到的圆
cv.circle(img, center=(circle[0], circle[1]), radius=circle[2],
color=(0, 0, 255), thickness=2)
# 画出圆心
cv.circle(img, center=(circle[0], circle[1]), radius=2,
color=(0, 0, 255), thickness=3)
cv.imshow('canny', img_thresh)
print(img.shape, cimg.shape)
img_concatenate = np.concatenate((cimg, img), axis = 1)
cv.imwrite('img_con.png', img_concatenate)
cv.imshow('img', img_concatenate)
cv.waitKey(0)

if __name__ == '__main__':
circle_detect()