判別數字圖片能否「一筆完成」

每張給定的數字圖片只有2種像素值,即0和255,如下所示:
實例1
現給定全黑的一張背景圖,用一支筆可以連續地在上下左右斜對角共8個方向移動,可以允許重複地經過一處。筆經過處像素值會變爲0,即變成白色。如果這樣操作後能得到一張如上所示的數字圖片,則稱該數字圖片可以「一筆完成」。

下面是不能「一筆完成」的數字圖片例子:
實例2
因爲要完成“6”中間部分的「白圈」,必須要把「筆」拿起來放到對應的位置移動。

將數字“6”用pandas可視化如下所示,這裏去掉像素值全爲0的部分列:

也就說,需要給定一個程序判斷是否有一堆「0」被一堆「255」圍住,如果是的話,這張數字圖片就是不能「一筆完成」的。我這裏用的辦法是深度搜索,往上下左右4個方向深搜,判斷圖片中有幾堆「0」。如果僅有1堆,那麼這個數字圖片可以「一筆完成」;反之。

代碼

mnist.npz的百度雲盤,密碼bwn1

import numpy as np

# 讀取函數,數據都被保存在mnist.npz
def load_data():
    data = np.load('./mnist.npz')
    X = data['X']
    return X

def DFS(X, row, col, visited):
    visited[row][col] = 1
    if X[row][col] == 255:
        return
    if row+1 < 28 and visited[row+1][col] == 0:
        DFS(X, row+1, col, visited)
    if col+1 < 28 and visited[row][col+1] == 0:
        DFS(X, row, col+1, visited)
    if row-1 >= 0 and visited[row-1][col] == 0:
        DFS(X, row-1, col, visited)
    if col-1 >= 0 and visited[row][col-1] == 0:
        DFS(X, row, col-1, visited)

if __name__ == '__main__':
    X = load_data()
    # X.shape = (10000, 28, 28)
    success = 0  # 可以「一筆完成」的數字圖片總數
    for t in range(10000):
        blocks = 0  # 數字圖片中存在幾堆「0」
        visited = np.zeros((28, 28))  # 標記數組
        for i in range(28):
            for j in range(28):
                if X[t][i][j] == 0 and visited[i][j] == 0:
                    DFS(X[t], i, j, visited)
                    blocks += 1
        if blocks == 1:
            success += 1

    print(success)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章