9路棋盤識別-程式碼備份

默涼發表於2020-09-28
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



相關文章