本期我們將一起學習如何使用計算機視覺技術識別棋子及其在棋盤上的位置
我們利用計算機視覺技術和卷積神經網絡(CNN)為這個項目創建分類算法,并確定棋子在棋盤上的位置。最終的應用程序會保存整個圖像并可視化的表現出來,同時輸出棋盤的2D圖像以查看結果。
01. 數據
我們對該項目的數據集有很高的要求,因為它最終會影響我們的實驗結果。我們在網上能找到的國際象棋數據集是使用不同的國際象棋集、不同的攝影機拍攝得到的,這導致我們創建了自己的數據集。我使用國際象棋和攝像機(GoPro Hero6 Black以“第一人稱視角”角度)生成了自定義數據集,這使我的模型更加精確。該數據集包含2406張圖像,分為13類(請參閱下文)。總結:這花費了我們很多時間,但是這使得訓練圖像盡可能地接近在應用程序中使用時所看到的圖像。
自定義數據集的細分
為了構建該數據集,我首先創建了capture_data.py,當單擊S鍵時,該視頻從視頻流中獲取一幀并將其保存。這個程序使我能夠無縫地更改棋盤上的棋子并一遍又一遍地捕獲棋盤的圖像,直到我建立了大量不同的棋盤配置為止。接下來,我創建了create_data.py,以使用下一部分中討論的檢測技術將其裁剪為單獨小塊。最后,我通過將裁剪后的圖像分成帶標簽的文件夾來對它們進行分類。
02. 棋盤檢測
對于棋盤檢測,我想做的事情比使用OpenCV函數findChessboardCorners復雜的多,但又不像CNN那樣高級。使用低級和中級計算機視覺技術來查找棋盤的特征,然后將這些特征轉換為外邊界和64個獨立正方形的坐標。該過程以Canny邊緣檢測和Hough變換生成的相交水平線、垂直線的交點為中心。層次聚類用于按距離對交叉點進行分組,并對各組取平均值以創建最終坐標(請參見下文)。
完整的棋盤檢測過程
03. 棋盤分類
項目伊始,我們想使用Keras / TensorFlow創建CNN模型并對棋子進行分類。但是,在創建數據集之后,僅考慮CNN的大小,單靠CNN就無法獲得想要的結果。為了克服這一障礙,我利用了ImageDataGenerator和transfer learning,它增加了我的數據并使用了其他預訓練的模型作為基礎。
創建CNN模型
為了使用GPU,我在云中創建并訓練了CNN模型,從而大大減少了訓練時間。快速提示:Google Colab是使用GPU快速入門的簡便方法。為了提高數據的有效性,我使用了ImageDataGenerator來擴展原始圖像并將模型暴露給不同版本的數據。ImageDataGenerator函數針對每個時期隨機旋轉,重新縮放和翻轉(水平)訓練數據,從本質上創建了更多數據。盡管還有更多的轉換選項,但這些轉換選項對該項目最有效。
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=5,
rescale=1./255,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255)
train_gen = datagen.flow_from_directory(
folder + '/train',
target_size = image_size,
batch_size = batch_size,
class_mode = 'categorical',
color_mode = 'rgb',
shuffle=True)
test_gen = test_datagen.flow_from_directory(
folder + '/test',
target_size = image_size,
batch_size = batch_size,
class_mode = 'categorical',
color_mode = 'rgb',
shuffle=False)
我們沒有從頭開始訓練模型,而是通過利用預先訓練的模型并添加了使用我的自定義數據集訓練的頂層模型來實現轉移學習。我遵循了典型的轉移學習工作流程:
1.從先前訓練的模型(VGG16)中獲取圖層。
from keras.applications.vgg16 import VGG16
model = VGG16(weights='imagenet')
model.summary()
2.凍結他們,以避免破壞他們在訓練回合中包含的任何信息。
3.在凍結層的頂部添加了新的可訓練層。
from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, Flatten
from keras.models import Model
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224,224,3))
# Freeze convolutional layers from VGG16
for layer in base_model.layers:
layer.trainable = False
# Establish new fully connected block
x = base_model.output
x = Flatten()(x)
x = Dense(500, activation='relu')(x)
x = Dense(500, activation='relu')(x)
predictions = Dense(13, activation='softmax')(x)
# This is the model we will train
model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['categorical_accuracy'])
4.在自定義數據集上訓練新層。
epochs = 10
history = model.fit(
epochs=epochs,
verbose = 1,
validation_data=test_gen)
model.save_weights('model_VGG16.h5')
當我們使用VGG16或VGG19作為預訓練模型創建模型時,由于驗證精度更高,因此選擇了使用VGG16的模型。另外,最佳epochs 是10。任何大于10的數均不會使驗證準確性的提高,也不會增加訓練與驗證準確性之間的差異。總結:轉移學習使我們可以充分利用深度學習在圖像分類中的優勢,而無需大型數據集。
04. 結果
為了更好地可視化驗證準確性,我創建了模型預測的混淆矩陣。通過此圖表,可以輕松評估模型的優缺點。優點:空-準確率為99%,召回率為100%;白棋和黑棋(WP和BP)-F1得分約為95%。劣勢:白騎士(WN)-召回率高(98%),但準確性卻很低(65%);白主教(WB)-召回率最低,為74%。
測試數據的混淆矩陣
05. 應用
該應用程序的目標是使用CNN模型并可視化每個步驟的性能。我們創建了cv_chess.py,它清楚地顯示了步驟,并創建了cv_chess_functions.py,它顯示了每個步驟的詳細信息。此應用程序保存實時視頻流中的原始幀,每個正方形的64個裁剪圖像以及棋盤的最終2D圖像。
print('Working...')
# Save the frame to be analyzed
cv2.imwrite('frame.jpeg', frame)
# Low-level CV techniques (grayscale & blur)
img, gray_blur = read_img('frame.jpeg')
# Canny algorithm
edges = canny_edge(gray_blur)
# Hough Transform
lines = hough_line(edges)
# Separate the lines into vertical and horizontal lines h_lines, v_lines = h_v_lines(lines)
# Find and cluster the intersecting
intersection_points = line_intersections(h_lines, v_lines) points = cluster_points(intersection_points)
# Final coordinates of the board
points = augment_points(points)
# Crop the squares of the board a organize into a sorted list x_list = write_crop_images(img, points, 0)
img_filename_list = grab_cell_files() img_filename_list.sort(key=natural_keys)
# Classify each square and output the board in Forsyth-Edwards Notation (FEN)
fen = classify_cells(model, img_filename_list)
# Create and save the board image from the FEN
board = fen_to_image(fen)
# Display the board in ASCII
print(board)
# Display and save the chessboard image
board_image = cv2.imread('current_board.png') cv2.imshow('current board', board_image)
print('Completed!')
-
數據
+關注
關注
8文章
7104瀏覽量
89295 -
計算機
+關注
關注
19文章
7525瀏覽量
88328 -
圖像
+關注
關注
2文章
1088瀏覽量
40515
原文標題:基于計算機視覺的棋盤圖像識別
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論