起因是我想做個自動走迷宮的外掛(其實是想做點實踐),所以我需要在游戲中捕捉畫面并自動尋路,然后再控制自動移動,此為第一部分:捕捉畫面。
一.思路
1.取得圖像迷宮
2.處理圖像
3.圖像分割
4.生成數(shù)組
二.代碼
首先我們得捕捉屏幕畫面,即獲得迷宮圖像,這里我是在steam上面找了一個迷宮小游戲作為捕捉對象
然后寫個捕捉屏幕畫面的函數(shù)
def VideoCapture():
imm = ImageGrab.grab() # 獲得當前屏幕
imm = cv2.cvtColor(np.array(imm), cv2.COLOR_RGB2GRAY) # 轉(zhuǎn)為opencv的灰度圖
imm = imm[35:1040, 450:1470] # 1080*1100 裁剪圖像,這是根據(jù)游戲畫面調(diào)整的數(shù)值
imm = cv2.resize(imm, (250, 250)) # 19 * 19 縮小圖像
return imm
然后如果顯示圖像就能看到:
接著我們需要對圖像進行處理,我們可以看到這個迷宮有三個對象:從上到下依次是巢,心,球。而我們是要操控球吃完所有的心再返回巢。所以 巢和心的是需要搜索路徑的終點,球是起點,但是在此之前,我們需要一個完整的迷宮地圖,所以我們要先找到這三個對象并涂白:
所以我們要進行模板匹配:
def match(target, template, color):
global object
# 獲得模板圖片的高寬尺寸
theight, twidth = template.shape[:2]
# 執(zhí)行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED
result = cv2.matchTemplate(target, template, cv2.TM_SQDIFF_NORMED)
# 歸一化處理
cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
# 尋找矩陣(一維數(shù)組當做向量,用Mat定義)中的最大值和最小值的匹配結(jié)果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 匹配值轉(zhuǎn)換為字符串
# 對于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趨近與0匹配度越好,匹配位置取min_loc
# 對于其他方法max_val越趨近于1匹配度越好,匹配位置取max_loc
strmin_val = str(min_val)
# 繪制矩形邊框,將匹配區(qū)域涂成白色
# min_loc:矩形定點
# (min_loc[0]+twidth,min_loc[1]+theight):矩形的寬高
# color:矩形的邊框顏色;2:矩形邊框?qū)挾?/span>
cv2.rectangle(target, min_loc, (min_loc[0] + twidth, min_loc[1] + theight), color, -1)
# 返回操作后圖像,以及對象的四點坐標
return [target, (int(min_loc[0]), int(min_loc[1]), int(min_loc[0] + twidth), int(min_loc[1] + theight))]
執(zhí)行后效果如圖所示:
然后我們要把圖像轉(zhuǎn)化為標準的迷宮圖像,黑白塊的大小要相等,這樣才方便轉(zhuǎn)化成數(shù)組形式,所以我們對圖像進行二值化后白色為可走趨于,黑色為障礙,接著通過腐蝕操作增大黑色趨于使之與白色塊大小接近。
def pic(imm):
ret, binary = cv2.threshold(imm, 200, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)# 二值化
k = np.ones((7, 7), np.uint8)#定義核
binary = cv2.erode(binary, k)# 腐蝕
return binary
然后大致數(shù)出可以劃分為19*19的色塊,計算出單個色塊的長度,然后定義每個色塊的近中心點(因為坐標只能整數(shù)而計算中心點會有小數(shù),一般略微靠近左上角比較準確),取其近中心點的顏色為整個色塊的顏色轉(zhuǎn)化為數(shù)組中:
def getBoard(imm):
board = [[0 for w in range(19)] for h in range(19)]#創(chuàng)建數(shù)組
for h in range(19):
for w in range(19):
if imm[13 * h + 5, 13 * w + 5] == np.uint8(255):#坐標轉(zhuǎn)換
board[h][w] = 255
return board
然后我們把得到的數(shù)組以圖像的形式打印出來看看:
對比一下原圖像,已經(jīng)實現(xiàn)了我們的目的。
最后我們再把其他信息獲取一下,比如對象位置轉(zhuǎn)化為數(shù)組坐標:
def getBoardIndex(cor):
index = (int((cor[1] - 5) / 13), int((cor[0] - 5) / 13))
return index
然后我們也方便日后的尋路算法應(yīng)用(這么小,很快?。?mark hidden color="red">文章來源:http://www.zghlxwxcb.cn/news/detail-465251.html
最后的最后給個運行代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-465251.html
startFlag = False
while True:
imm = VideoCapture()
if startFlag:
imm, ball = match(imm, cv2.imread("ball.png", 0), (255, 255, 255))
imm, home = match(imm, cv2.imread("home.png", 0), (255, 255, 255))
imm, heart = match(imm, cv2.imread("heart.png", 0), (255, 255, 255))
imm = pic(imm)
board = getBoard(imm)
cv2.imwrite("board.png", np.array(board, dtype=np.uint8))
ball = getBoardIndex(getPointCor(ball))
heart = getBoardIndex(getPointCor(heart))
home = getBoardIndex(getPointCor(home))
print(ball, heart, home)
key = cv2.waitKey(1)
if key == ord('q'):
break
elif key == ord('g'):
startFlag = True
cv2.imshow("im", imm)
key = cv2.waitKey(1)
if key == ord('q'):
break
elif key == ord('g'):
startFlag = True
cv2.imshow("im", imm)
到了這里,關(guān)于opencv-python 將圖像迷宮轉(zhuǎn)為迷宮數(shù)組的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!