基本實現思路是使用DNF Extractor將物品的貼圖添加上特定顏色的像素塊,然后再在截圖中尋找特點的像素定位物品位置。
我們以數據芯片
為例
DNF Extractor替換貼圖
斷網安裝DNF Extractor 然后防火牆禁用網絡連接。
打開npk文件,dnf安裝路徑下ImagePacks2文件夾,sprite_item.NPK。如圖所示數據芯片的貼圖是在fielf_material.img
下面的第97個。
我們右鍵提取貼圖。然后使用ps在提取的圖片上放置一個色塊(RGB:255,237,99)。最后右鍵替換貼圖,替換貼圖前可以將nkp文件備份一份。
定位物品位置
進入游戲我們發現掉落物品的貼圖已經被替換了。
sp1.jpg:
使用像素RGB定位物品位置
from PIL import Image
# 打開要處理的圖像
img_src = Image.open('sp1.jpg')
# 轉換圖片的模式為RGB
img = img_src.convert('RGB')
r, g, b = 255, 237, 99
pixs = []
# 遍歷圖片獲取指定像素的點
for x in range(img.size[0]):
for y in range(img.size[1]):
pix = img.getpixel((x, y))
if (pix[0] == r) and (g - 3 <= pix[1] <= g + 3) and (b - 3 <= pix[2] <= b + 3):
pixs.append([x, y])
new_img = Image.new("RGB", img.size)
pixTuple = (r, g, b)
# 新建圖片在圖片上畫點
for i in pixs:
new_img.putpixel((i[0], i[1]), pixTuple)
new_img.save("new_sp1.png")
new_sp1.jpg:
去除噪點
使用九宮格法去除噪點。判斷當前像素周圍一圈的像素色值是否與當前的相同,當周圍一圈八個像素至少有七個相同時,我們就認為當前像素不是噪點。
如下圖所示的中間像素即為噪點。
from PIL import Image
# 打開要處理的圖像
img_src = Image.open('sp1.jpg')
# 轉換圖片的模式為RGB
img = img_src.convert('RGB')
def checkPixel(r,g,b,pix):
if (pix[0] == r) and (g - 3 <= pix[1] <= g + 3) and (b - 3 <= pix[2] <= b + 3):
return True
else:
return False
r, g, b = 255, 237, 99
pixels = []
# 遍歷圖片獲取指定像素的點
for x in range(img.size[0]):
for y in range(img.size[1]):
pix = img.getpixel((x, y))
if checkPixel(r,g,b,pix):
pix_set = []
for m in range( x - 1, x + 2):
for n in range( y - 1, y + 2):
_pix = img.getpixel((m, n))
if checkPixel(r,g,b,_pix):
pix_set.append(_pix)
# 當九宮格中其他8格都匹配獲取像素
if len(pix_set) >= 7:
pixels.append([x, y])
new_img = Image.new("RGB", img.size)
pixTuple = (r, g, b)
# 新建圖片在圖片上畫點
for i in pixels:
new_img.putpixel((i[0], i[1]), pixTuple)
new_img.save("new_sp1.png")
可以發現絕大部分噪點已經清除了。
多個物品
在使用的過程中發現色塊的像素過多,當檢測一個物品時只需要在目標色值像素數組pixels中合理的選擇一個當做當前物品的位置即可。當檢測多個物品時,我們在pixels數組中無法直接知道物品的個數和位置信息。所以我們選擇使用較少色塊的像素,使用3x3色塊。當使用九宮格篩選的時候剛好可以篩選出一個像素。
當時在使用過程中,我們發現會出現一些干擾點。dnf游戲畫面中會存在一些色值和目標相同的像素,所以為了盡量避免干擾,我們在3x3色塊外再加一圈特定的其讓色值的輔助像素(為了更准確一點可以多加幾圈)。將色塊變成5x5。在原來九宮格判斷的基礎上再判斷外面一層的色塊是不是指定的色值。
測試多個物品
#[[520, 308], [671, 430]] 兩個像素的位置信息,對應着兩個數據芯片
print(pixels)