import cv2
import numpy as np
import recognition最初版1
import time
ticks1 = time.time()
def cv_show(neme,img):
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread('ce3/26.jpg') # 76 需開 42 不開
# img = cv2.imread('wjz/1.jpg')
imgPP = img.copy()
h, w = img.shape[:2]
mtx = np.array([[509.87562045, 0, 418.23245649], [0, 683.80709577, 309.94016309], [0, 0, 1]])
dist = np.array([[-0.47360781, 0.29612718, 0.00107295, -0.0005097, -0.13855614]])
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0, (w, h))
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# img = cv2.imread('jz_hou/2.jpg')
blur1 = cv2.GaussianBlur(dst, (5, 5), 0)
hsv = cv2.cvtColor(blur1, cv2.COLOR_BGR2HSV)
low_blue = np.array([12, 0, 10])
high_blue = np.array([65, 255, 255])
# low_blue = np.array([20, 50, 40]) # 黃色棋盤
# high_blue = np.array([65, 255, 255])
gray = cv2.inRange(hsv, low_blue, high_blue)
Sobel_x = cv2.Sobel(gray, cv2.CV_16S, 1, 0)
Sobel_y = cv2.Sobel(gray, cv2.CV_16S, 0, 1)
absX = cv2.convertScaleAbs(Sobel_x) # 轉 uint8 格式
absy = cv2.convertScaleAbs(Sobel_y) # 轉 uint8 格式
res = cv2.addWeighted(absX, 1, absy, 1, 0) # 融合
# cv_show('sd', res)
# cv_show('sd', gray)
# 二值
ret, thresh = cv2.threshold(res, 127, 255, cv2.THRESH_BINARY)
# thresh = cv2.threshold(res, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('sd', thresh)
# 繪製大矩形
res1 = cv2.rectangle(res, (0, 0), (799, 599), (255, 255, 255), 1)
# 外輪廓檢測
# contours, hierarchy = cv2.findContours(gaussImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 原
contours1, hierarchy1 = cv2.findContours(res1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# # 檢視所有繪製輪廓
# for c in contours:
# x, y, w, h = cv2.boundingRect(c)
#
# # 繪製輪廓
# sk = cv2.rectangle(dst, (x, y), (x+w, y+h), (0, 255, 0), 2)
# # # 繪製輪廓
# sd = cv2.drawContours(thresh, contours, -1, (255, 255, 255), 2)
# cv_show('sd', sd)
# 自寫方法
dange = [] # 中心點
w_h = [] # 高和寬 如果大於閾值就需要旋轉 目前只要高就行了
# 檢視每個輪廓並畫出
for i in range(len(contours1)):
cnt = contours1[i]
x, y, w, h = cv2.boundingRect(cnt) # 最小矩形包裹
if h > 300 and 700 > w > 300:
# cv2.rectangle 是繪製外界矩形
img = cv2.rectangle(dst, (x, y), (x+w, y+h), (255, 0, 0), 2)
x = int(((x+w)-x)/2+x)
y = int(((y+h)-y)/2+y)
dange.append([x, y])
w_h.append([h])
cv_show('sad', img)
# print(dange[0][0], dange[0][1]) # 計算矩形中心點
print(dange)
print(w_h)
# 判斷是否為空列表
kong = []
if dange != kong:
k2 = np.array(dange[0]) # 必須轉換型別,不然無法進行 if判斷
if w_h != kong:
h1 = np.array(w_h[0])
if dange == kong:
k2 = [0, 0]
# 輪廓排序
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:1]
# 取出單個輪廓值
pentagram = contours[0]
epsilon = 0.1 * cv2.arcLength(pentagram, True)
approx = cv2.approxPolyDP(pentagram, epsilon, True)
# print(approx)
e, g, m = approx.shape
print(e)
if e == 4 and h1 > 420:
print("需要擺正")
z1 = []
if 355 < k2[0] < 445 and 300 < k2[1] < 370:
z1.append(1)
if z1 and e == 4:
print("在範圍內")
print(e)
# # 繪製輪廓
# sd = cv2.drawContours(dst, pentagram, -1, (0, 255, 255), 10)
# cv_show('sd', sd)
# if e == 4:
y1 = [] # Y軸
y2 = []
x1 = [] # x軸
x2 = []
for i in approx:
for j in i: # Y軸大小 分上下
q = [j[1]]
y1.append(q)
y2.append(q)
x1.append(q)
x2.append(q)
# 下
y_max1 = np.argmax(y1) # Y軸 第一大
y2[np.argmax(y2)] = np.min(y2) # 將Y軸最大的變成最小的
y_max2 = np.argmax(y2) # Y軸 第二大
# print(approx[y_max1][0]) # 下 第一大
# print(approx[y_max2][0]) # 下 第二大
# 下 分左右
sz = [approx[y_max1][0][0], approx[y_max2][0][0]]
if approx[y_max1][0][0] > approx[y_max2][0][0]: # 右
xy = approx[y_max1][0]
xz = approx[y_max2][0]
if approx[y_max1][0][0] < approx[y_max2][0][0]: # 左
xz = approx[y_max1][0]
xy = approx[y_max2][0]
# 上
x_max1 = np.argmin(x1) # Y軸 第一小
x2[np.argmin(x2)] = np.max(x2) # 將Y軸最小的變成最大的
x_max2 = np.argmin(x2) # Y軸 第二小
# print(approx[x_max1][0]) # 上 第一小
# print(approx[x_max2][0]) # 上 第二小
# 上 分左右
sz = [approx[x_max1][0][0], approx[x_max2][0][0]]
if approx[x_max1][0][0] > approx[x_max2][0][0]: # 右
sy = approx[x_max1][0]
sz = approx[x_max2][0]
if approx[x_max1][0][0] < approx[x_max2][0][0]: # 左
sz = approx[x_max1][0]
sy = approx[x_max2][0]
sz1 = sz[0]+3, sz[1]+3
sy1 = sy[0], sy[1]
xz1 = xz[0]+4, xz[1]-4
xy1 = xy[0]-3, xy[1]-3
# if sz1, sy1, xz1, xy1
srcPoints = np.vstack((sz1, sy1, xz1, xy1))
# 繪製4點 (藍綠紅)
cv2.circle(dst, tuple(sz1), 2, (255, 0, 0), 3)
cv2.circle(dst, tuple(sy1), 2, (0, 255, 0), 3)
cv2.circle(dst, tuple(xz1), 2, (0, 0, 255), 3)
cv2.circle(dst, tuple(xy1), 2, (255, 255, 0), 3)
cv2.imshow('imgPP', dst)
cv2.waitKey(0)
srcPoints = np.float32(srcPoints)
# print(srcPoints)
# 目標的畫素值大小
# 以下引數解釋:96為解析度,可在圖片的屬性的詳細資訊裡查詢。
# 29.7,21分別是A4紙(需校正尺寸物體)的長和寬,單位是cm。2.54為英寸的換算
long = 10*96/2.54
short = 10*96/2.54
# 設定目標畫布的大小
canvasPoints = np.array([[0, 0], [int(long), 0], [0, int(short)], [int(long), int(short)]])
canvasPoints = np.float32(canvasPoints)
# print(canvasPoints)
# 計算轉換矩陣(原4點,目標4點)
perspectiveMatrix = cv2.getPerspectiveTransform(srcPoints, canvasPoints)
# 完成透視變換
perspectiveImg = cv2.warpPerspective(dst, perspectiveMatrix, (int(long), int(short)))
# cv2.imshow('perspectiveImg', perspectiveImg)
# # cv2.imwrite('3b/3.jpg', perspectiveImg) # 存
cv2.waitKey(0)
# 透視變換後
# 灰度
gray = cv2.cvtColor(perspectiveImg, cv2.COLOR_BGR2GRAY)
_x = cv2.Sobel(gray, cv2.CV_16S, 1, 0) # Y
_y = cv2.Sobel(gray, cv2.CV_16S, 0, 1) # X
absX = cv2.convertScaleAbs(_x)
ab = cv2.convertScaleAbs(_y)
res = cv2.addWeighted(absX, 1, ab, 1, 0) # 合
# cv_show('sd', res)
# 二值
ret, thresh = cv2.threshold(res, 60, 255, cv2.THRESH_BINARY)
cv_show('sd', thresh)
# 高斯濾波
gaussImage = cv2.GaussianBlur(thresh, (3, 3), 0)
# 腐蝕
kernel = np.ones((3, 3), np.uint8)
lai = cv2.erode(gaussImage, kernel, iterations=1)
# cv_show('sd', lai)
# # 膨脹
# kernel2 = np.ones((3, 3), np.uint8)
# erosion = cv2.dilate(lai, kernel2, iterations=1)
# cv_show('sd', lai)
# 距離變換 + 歸一化
dist_transform = cv2.distanceTransform(lai, 1, 5)
# 繪製 cv2.distanceTransform 操作後的影像
dist1 = cv2.convertScaleAbs(dist_transform)
dist2 = cv2.normalize(dist_transform, None, 255, 0, cv2.NORM_MINMAX, cv2.CV_8UC1)
cv_show('sda', dist2)
# 二值
ret1, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
cv_show('sda', sure_fg)
image = np.clip(sure_fg, 0, 255)
image1 = np.array(image, np.uint8)
# # 輪廓
# # contours, hierarchy = cv2.findContours(gaussImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# # 外輪廓
contours, hierarchy = cv2.findContours(image1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 【y1:y2, x1:x2】 x行y列
k1 = []
# 繪製全部 外接矩形
for i in range(len(contours)):
cnt = contours[i]
# print(i)
x, y, w, h = cv2.boundingRect(cnt) # 最小矩形包裹
# print(x, y, w, h)
k1.append([x, y])
# 上 Y=0 下 Y=377 左 X=0 右 X=377
k2 = np.array(k1)
# print(k2)
# print(k2[:, 0])
# print(k2)
z1 = []
y1 = []
s1 = []
x1 = []
# XY 大小判斷
for i in range(len(k2)):
if 15 < k2[i, 0] < 40 and 50 < k2[i, 1] < 330:
z1.append(k2[i, 0])
if 15 < k2[i, 1] < 50 and 51 < k2[i, 0] < 315:
s1.append(k2[i, 1])
if 360 > k2[i, 0] > 340 and 50 < k2[i, 1] < 315:
y1.append(k2[i, 0])
if 337 < k2[i, 1] < 365 and 50 < k2[i, 0] < 315:
x1.append(k2[i, 1])
fx = [[np.array(z1).shape], [np.array(y1).shape], [np.array(s1).shape], [np.array(x1).shape]]
fx1 = np.argmax(fx)
if fx1 == 0:
print('方向為左')
imgInfo = perspectiveImg.shape
height = imgInfo[0]
width = imgInfo[1]
deep = imgInfo[2]
# 定義一個旋轉矩陣
matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 270, 1) # mat rotate 1 center 2 angle 3 縮放係數
dst = cv2.warpAffine(perspectiveImg, matRotate, (height, width))
cv_show('sd', dst)
if fx1 == 1:
print('方向為右')
imgInfo = perspectiveImg.shape
height = imgInfo[0]
width = imgInfo[1]
deep = imgInfo[2]
# 定義一個旋轉矩陣
matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 90, 1) # mat rotate 1 center 2 angle 3 縮放係數
dst = cv2.warpAffine(perspectiveImg, matRotate, (height, width))
cv_show('sd', dst)
if fx1 == 2:
print('方向為上')
imgInfo = perspectiveImg.shape
height = imgInfo[0]
width = imgInfo[1]
deep = imgInfo[2]
# 定義一個旋轉矩陣
matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 0, 1) # mat rotate 1 center 2 angle 3 縮放係數
dst = cv2.warpAffine(perspectiveImg, matRotate, (height, width))
cv_show('sd', dst)
# cv2.imwrite('jz_hou/1.jpg', perspectiveImg)
if fx1 == 3:
print('方向為下')
imgInfo = perspectiveImg.shape
height = imgInfo[0]
width = imgInfo[1]
deep = imgInfo[2]
# 定義一個旋轉矩陣
matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 180, 1) # mat rotate 1 center 2 angle 3 縮放係數
dst = cv2.warpAffine(perspectiveImg, matRotate, (height, width))
cv_show('sd', dst)
b1 = recognition最初版1.black(dst)
w1 = recognition最初版1.white(dst)
b1_ = np.array(b1)
w1_ = np.array(w1)
# print(s.dtype)
# print(b1_)
# print(w1_)
# w1_.size
if w1_.size + b1_.size == 2:
print(b1_)
if b1_.size == 81 and w1_.size == 81:
s1 = b1 + w1
e = recognition最初版1.p3(s1)
# print(e)
if e == 1:
pass
else:
print(s1.reshape(9, 9))
# print(s1)
# u = ''
# for i in range(len(s1)):
# u = u + str(s1[i])
# print(u)
else:
# print('棋盤未找到4頂點')
# ticks2 = time.time()
# print(ticks2-ticks1)
if z1:
pass
elif k2[0] == 0:
print(82)
elif k2[1] > 370 or k2[1] < 300:
if k2[1] > 300:
print("往上點")
if k2[1] < 300:
print("往下點")
elif k2[0] > 355 or k2[0] < 445:
if k2[0] > 400:
print("往左點")
if k2[0] < 400:
print("往右點")
import numpy as np
import cv2
def cv_show(neme,img):
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def jian(thresh): # 自定義塗黑
# 4點定位
rows, cols = thresh.shape[:2]
pt_1 = [cols * 0.05, rows * 0.07]
pt_2 = [cols * 0.97, rows * 0.07]
pt_3 = [cols * 0.97, rows * 0.95]
pt_4 = [cols * 0.05, rows * 0.95]
# 資料格式轉換
vertices = np.array([[pt_1, pt_2, pt_3, pt_4]], dtype=np.int32)
# 將需要填充的圖片放入括號中
mask = np.zeros_like(thresh)
# 塗黑
if len(mask.shape) == 2:
cv2.fillPoly(mask, vertices, 255)
cv_show('mask', mask)
# 引數:填充圖片,塗黑圖片
s = cv2.bitwise_and(thresh, mask)
cv_show('mask', s)
return s
def qw(x, y): # 是否在棋盤內
zxd = [x, y]
Fw = [[15, 35], [362, 356]]
if Fw[0][0] <= zxd[0] <= Fw[1][0] and Fw[0][1] <= zxd[1] <= Fw[1][1]:
return 1
else:
return 2
def qw1(x, y): # 報錯
A5 = [] # 線左右
A6 = [] # 線上下
zxd = [x, y]
# 先報錯
# 下在 線上附近的
b = []
for y in range(55, 336, 35):
for x in range(37, 342, 38):
b.append([[x - 19, y - 17], [x - 15, y - 13], [x + 15, y + 14], [x + 19, y + 18]])
num = 0
for j in b:
num += 1
# print(j)
if j[1][1] <= zxd[1] <= j[2][1]:
if j[0][0] <= zxd[0] < j[1][0] or j[2][0] < zxd[0] <= j[3][0]:
print("左右錯", num)
A5.append(num)
return A5
elif j[1][0] <= zxd[0] <= j[2][0]:
if j[0][1] <= zxd[1] < j[1][1] or j[2][1] < zxd[1] <= j[3][1]:
print('上下錯', num)
A6.append(num)
return A6
def qw2(x, y): # 報錯
A1 = [] # 內圈格
zxd = [x, y]
# 格
num = 0
c = []
for y in range(73, 319, 35):
for x in range(56, 323, 38):
c.append([[x - 4, y - 4], [x + 4, y + 4]])
# print(c)
for i in c:
num += 1
# print(i)
if i[0][0] < zxd[0] < i[1][0] and i[0][1] < zxd[1] < i[1][1]:
# print('格子裡', i)
# print('附近錯', num)
A1.append(num)
return A1
def qw3(x, y): # 報錯
A2 = [] # 外圈上下
zxd = [x, y]
# 外圈格1 橫向
num = 0
d = []
for y in range(40, 356, 314): # 兩次 大步長
for x in range(20, 364, 38): # 十次 小步長
d.append([[x - 4, y - 4], [x + 4, y + 4]])
# print(d)
for w in d:
num += 1
# print(i)
if w[0][0] < zxd[0] < w[1][0] and w[0][1] < zxd[1] < w[1][1]:
# print('格圈上下', num)
A2.append(num)
return A2
def qw4(x, y): # 報錯
A3 = [] # 外圈左右
zxd = [x, y]
# 外圈格2 縱向
num = 0
e = []
for x in range(20, 364, 343): # 兩次 大步長 X軸
for y in range(76, 322, 35): # 八次 *7+1 小步長 Y軸
e.append([[x - 4, y - 4], [x + 4, y + 4]])
for i in e:
num += 1
# print(i)
if i[0][0] < zxd[0] < i[1][0] and i[0][1] < zxd[1] < i[1][1]:
# print('格圈左右', num)
A3.append(num)
return A3
def qw5(x, y): # 單個棋子位置
# 黑 1~81
A4 = [] # 棋子內
zxd = [x, y]
# 下對的
a = []
for y in range(55, 336, 35):
for x in range(37, 342, 38):
a.append([[x - 15, y - 13], [x + 15, y + 14]])
num = 0
for i in a:
num += 1
# print(i)
if i[0][0] <= zxd[0] <= i[1][0] and i[0][1] <= zxd[1] <= i[1][1]:
# print('下對了', i, num)
# print('正確', num)
A4.append(num)
return A4
def pds(x2, a): # 黑棋子
# 生成比對矩陣
checkerboard = np.arange(1, 82)
for i in a:
q = []
for e in checkerboard:
if i == e:
q.append(1)
else:
q.append(0)
x2 = x2 + q
return x2
def pds1(x1, a): # 白棋子
checkerboard = np.arange(1, 82)
for i in a:
q = []
for e in checkerboard:
if i == e:
q.append(2)
else:
q.append(0)
x1 = x1 + q
return x1
# def chess_pieces(x, y):
# s1 = [] # 報錯
# s2 = [] # 棋子
# a = qw(x, y) # 需要替換括號內 # 判斷是否在棋盤內
# if a == 1: # 1為棋盤內
# a1 = qw1(x, y) # 需要替換括號內 # 判斷是否有報錯
# s1.append(a1)
# a2 = qw2(x, y) # 需要替換括號內 # 判斷棋子位置
# s2.append(a2[0])
# if a == 2: # 2為棋盤外
# print('棋盤外')
# 抓取白棋子
# img = cv2.imread('ts_hou/22.jpg')
# imgPP = img.copy()
def white(imgPP):
blur1 = cv2.GaussianBlur(imgPP, (5, 5), 0)
hsv = cv2.cvtColor(blur1, cv2.COLOR_BGR2HSV)
low_blue = np.array([50, 0, 130])
high_blue = np.array([255, 80, 255])
gray = cv2.inRange(hsv, low_blue, high_blue)
cv_show('s', gray)
# 開運算
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel, iterations=2)
cv_show('sda', opening)
q = jian(opening)
# 距離變換 + 歸一化
dist_transform = cv2.distanceTransform(q, cv2.DIST_L2, 5)
# 繪製 cv2.distanceTransform 操作後的影像
dist1 = cv2.convertScaleAbs(dist_transform)
dist2 = cv2.normalize(dist_transform, None, 255, 0, cv2.NORM_MINMAX, cv2.CV_8UC1)
cv_show('sda', dist2)
# 二值
ret1, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
cv_show('sda', sure_fg)
# 開運算
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(sure_fg, cv2.MORPH_OPEN, kernel, iterations=1)
cv_show('sda', opening)
# 判斷是否為空棋盤
cae = opening[35:362, 15:356] # 擷取棋盤
cv_show('sda', cae)
ju = np.mean(cae)
if ju == 0: # 如果平均值等於0,就為空棋盤 (無黑子)
# 生成空矩陣
ks = np.array(np.zeros(81), int)
return ks
else:
# 檢測輪廓需要轉換
image = np.clip(opening, 0, 255)
image1 = np.array(image, np.uint8)
# # 外輪廓
contours, hierarchy = cv2.findContours(image1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 正常範圍
q1 = [] # 棋子
s1 = [] # 報錯 線 上下左右
s2 = [] # 報錯 格內
s3 = [] # 報錯 外圈上下
s4 = [] # 報錯 外圈左右
# 超出範圍
c1 = [] # 報錯 線 上下左右
c2 = [] # 報錯 格內
c3 = [] # 報錯 外圈上下
c4 = [] # 報錯 外圈左右
c5 = [] # 棋子
for i in contours:
x, y, w, h = cv2.boundingRect(i)
if w > 30 or h > 30: # 處理超過正常範圍
# print(x, y, w, h)
x1 = int(w/2+x)
y1 = int(h/2+y)
print(1)
# print(qb.qw(x1, y1))
# qb = qb.qw(x1, y1)
# print(qb, '位置錯誤')
a = qw(x1, y1) # 判斷是否在棋盤範圍內
if a == 1: # 1為棋盤內
a1 = qw1(x1, y1) # 報錯 線 上下左右
a2 = qw2(x1, y1) # 報錯 格內
a3 = qw3(x1, y1) # 報錯 外圈上下
a4 = qw4(x1, y1) # 報錯 外圈左右
if a1:
c1.append(a1[0])
if a2:
c2.append(a2[0])
if a3:
c3.append(a3[0])
if a4:
c4.append(a4[0])
q = qw5(x1, y1) # 判斷棋子位置
if q:
c5.append(q[0])
# if a == 2: # 2為棋盤外
# print('棋盤外')
# L.append(i)
# cv2.rectangle 繪製外界矩形
if w < 30 or h < 30: # 處理正常範圍
# 正常範圍內
# img = cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
x2 = int(w/2+x)
y2 = int(h/2+y)
a = qw(x2, y2) # 判斷是否在棋盤範圍內
if a == 1: # 1為棋盤內
a1 = qw1(x2, y2) # 報錯 線 上下左右
a2 = qw2(x2, y2) # 報錯 格內
a3 = qw3(x2, y2) # 報錯 外圈上下
a4 = qw4(x2, y2) # 報錯 外圈左右
if a1:
s1.append(a1[0])
if a2:
s2.append(a2[0])
if a3:
s3.append(a3[0])
if a4:
s4.append(a4[0])
q = qw5(x2, y2) # 判斷棋子位置
if q:
q1.append(q[0])
# if a == 2: # 2為棋盤外
# print('棋盤外')
# print(s1)
# print(s2)
# print(s3)
# print(s4)
# print(q1)
# 格內
B = {1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 17,
9: 11, 10: 12, 11: 13, 12: 13, 13: 15, 14: 16, 15: 17, 16: 17,
17: 29, 18: 30, 19: 31, 20: 32, 21: 33, 22: 34, 23: 35, 24: 36,
25: 29, 26: 30, 27: 31, 28: 32, 29: 33, 30: 34, 31: 35, 32: 36,
33: 47, 34: 48, 35: 49, 36: 50, 37: 51, 38: 52, 39: 53, 40: 54,
41: 47, 42: 48, 43: 49, 44: 50, 45: 51, 46: 52, 47: 53, 48: 54,
49: 65, 50: 66, 51: 67, 52: 68, 53: 69, 54: 70, 55: 71, 56: 72,
57: 65, 58: 66, 59: 67, 60: 68, 61: 69, 62: 70, 63: 71, 64: 72}
# 外圈 上下
C = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 9,
11: 73, 12: 74, 13: 75, 14: 76, 15: 77, 16: 78, 17: 79, 18: 80,
19: 81, 20: 81}
# 外圈 左右
D = {1: 10, 2: 19, 3: 28, 4: 37, 5: 46, 6: 55, 7: 64, 8: 73,
9: 9, 10: 18, 11: 27, 12: 36, 13: 45, 14: 54, 15: 63, 16: 72}
# 轉換 1~81
# 黑
a1_ = [] # 格內
for k in s2:
a1_.append(B[k])
# a2 = [] # 外圈上下
for k in s3:
a1_.append(C[k])
# a3 = [] # 外圈左右
for k in s4:
a1_.append(D[k])
for k in s1:
a1_.append(k)
# print(a1_)
# 超出大小範圍位置判斷
a2_ = [] # 格內
# print(s2)
for k in c2:
a2_.append(B[k])
# a2 = [] # 外圈上下
for k in c3:
a2_.append(C[k])
# a3 = [] # 外圈左右
for k in c4:
a2_.append(D[k])
for k in c1:
a2_.append(k)
if a2_:
# return print(a2_[0], '白棋子擺放太過密集')
t1 = a2_[0]
return t1
else:
if a1_:
# return print(a1_[0], '白棋子擺放位置錯誤')
t2 = a1_[0]
return t2
# print(1)
else:
# print(q1)
# 矩陣初始化
x = np.array(np.zeros(81), int)
c4 = np.array(pds1(x, q1)) # 白
return c4
# c5 = c4.reshape(9, 9)
# print(c5.ndim)
# img = cv2.imread('ts_hou/22.jpg')
# imgPP = img.copy()
# white(imgPP)
def p3(s):
for q in s:
if q >= 3:
return 1
def black(img):
# # 抓取黑棋子
# img = cv2.imread('ts_hou/25.jpg')
# # img = cv2.imread('jqces/1_.jpg')
# 灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv_show('s', thresh)
# 開運算
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
cv_show('sda', opening)
# q = jian(opening)
# 距離變換 + 歸一化
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
# 繪製 cv2.distanceTransform 操作後的影像
dist1 = cv2.convertScaleAbs(dist_transform)
dist2 = cv2.normalize(dist_transform, None, 255, 0, cv2.NORM_MINMAX, cv2.CV_8UC1)
cv_show('sda', dist2)
# 二值
ret1, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
cv_show('sda', sure_fg)
# 開運算
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(sure_fg, cv2.MORPH_OPEN, kernel, iterations=1)
cv_show('sda', opening)
# 判斷是否為空棋盤
cae = opening[35:362, 15:356] # 擷取棋盤
cv_show('sda', cae)
ju = np.mean(cae)
if ju == 0: # 如果平均值等於0,就為空棋盤 (無黑子)
# 生成空矩陣
ks = np.array(np.zeros(81), int)
return ks
else:
# 檢測輪廓需要轉換
image = np.clip(opening, 0, 255)
image1 = np.array(image, np.uint8)
# # 外輪廓
contours, hierarchy = cv2.findContours(image1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 正常範圍
q1 = [] # 棋子
s1 = [] # 報錯 線 上下左右
s2 = [] # 報錯 格內
s3 = [] # 報錯 外圈上下
s4 = [] # 報錯 外圈左右
# 超出範圍
c1 = [] # 報錯 線 上下左右
c2 = [] # 報錯 格內
c3 = [] # 報錯 外圈上下
c4 = [] # 報錯 外圈左右
c5 = [] # 棋子
for i in contours:
x, y, w, h = cv2.boundingRect(i)
if w > 15 or h > 15: # 處理超過正常範圍
# print(x, y, w, h)
x1 = int(w/2+x)
y1 = int(h/2+y)
# print(qb.qw(x1, y1))
# qb = qb.qw(x1, y1)
# print(qb, '位置錯誤')
a = qw(x1, y1) # 判斷是否在棋盤範圍內
if a == 1: # 1為棋盤內
a1 = qw1(x1, y1) # 報錯 線 上下左右
a2 = qw2(x1, y1) # 報錯 格內
a3 = qw3(x1, y1) # 報錯 外圈上下
a4 = qw4(x1, y1) # 報錯 外圈左右
if a1:
c1.append(a1[0])
if a2:
c2.append(a2[0])
if a3:
c3.append(a3[0])
if a4:
c4.append(a4[0])
q = qw5(x1, y1) # 判斷棋子位置
if q:
c5.append(q[0])
# if a == 2: # 2為棋盤外
# print('棋盤外')
# L.append(i)
# cv2.rectangle 繪製外界矩形
if w < 15 or h < 15: # 處理正常範圍
# 正常範圍內
img = cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
x2 = int(w/2+x)
y2 = int(h/2+y)
a = qw(x2, y2) # 判斷是否在棋盤範圍內
if a == 1: # 1為棋盤內
a1 = qw1(x2, y2) # 報錯 線 上下左右
a2 = qw2(x2, y2) # 報錯 格內
a3 = qw3(x2, y2) # 報錯 外圈上下
a4 = qw4(x2, y2) # 報錯 外圈左右
if a1:
s1.append(a1[0])
if a2:
s2.append(a2[0])
if a3:
s3.append(a3[0])
if a4:
s4.append(a4[0])
q = qw5(x2, y2) # 判斷棋子位置
if q:
q1.append(q[0])
# if a == 2: # 2為棋盤外
# print('棋盤外')
# print(s1)
# print(s2)
# print(s3)
# print(s4)
# print(q1)
# 格內
B = {1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 17,
9: 11, 10: 12, 11: 13, 12: 13, 13: 15, 14: 16, 15: 17, 16: 17,
17: 29, 18: 30, 19: 31, 20: 32, 21: 33, 22: 34, 23: 35, 24: 36,
25: 29, 26: 30, 27: 31, 28: 32, 29: 33, 30: 34, 31: 35, 32: 36,
33: 47, 34: 48, 35: 49, 36: 50, 37: 51, 38: 52, 39: 53, 40: 54,
41: 47, 42: 48, 43: 49, 44: 50, 45: 51, 46: 52, 47: 53, 48: 54,
49: 65, 50: 66, 51: 67, 52: 68, 53: 69, 54: 70, 55: 71, 56: 72,
57: 65, 58: 66, 59: 67, 60: 68, 61: 69, 62: 70, 63: 71, 64: 72}
# 外圈 上下
C = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 9,
11: 73, 12: 74, 13: 75, 14: 76, 15: 77, 16: 78, 17: 79, 18: 80,
19: 81, 20: 81}
# 外圈 左右
D = {1: 10, 2: 19, 3: 28, 4: 37, 5: 46, 6: 55, 7: 64, 8: 73,
9: 9, 10: 18, 11: 27, 12: 36, 13: 45, 14: 54, 15: 63, 16: 72}
# 轉換 1~81
# 黑
a1_ = [] # 格內
for k in s2:
a1_.append(B[k])
# a2 = [] # 外圈上下
for k in s3:
a1_.append(C[k])
# a3 = [] # 外圈左右
for k in s4:
a1_.append(D[k])
for k in s1:
a1_.append(k)
# print(a1_)
# 超出大小範圍位置判斷
a2_ = [] # 格內
# print(s2)
for k in c2:
a2_.append(B[k])
# a2 = [] # 外圈上下
for k in c3:
a2_.append(C[k])
# a3 = [] # 外圈左右
for k in c4:
a2_.append(D[k])
for k in c1:
a2_.append(k)
if a2_:
# return print(a2_[0], '黑棋子擺放太過密集')
t1 = a2_[0]
return t1
else:
if a1_:
# return print(a1_[0], '黑棋子擺放位置錯誤')
t2 = a1_[0]
return t2
else:
# print(q1)
# 矩陣初始化
x = np.array(np.zeros(81), int)
c4 = np.array(pds(x, q1)) # 黑
# print(c4)
return c4