python Realizes Lianliankan Assistance (Image Recognition)
- 2021-07-22 10:16:50
- OfStack
Personal interest, using python to realize the auxiliary program of Lianliankan, and summarize the realization process and knowledge points.
General thinking
1. Get the window of Lianliankan program and put it in front of it
2. Screenshot of the game interface, cut each 1 small icon and form a 2-dimensional list composed of small icons
3. Traverse the 2D list of pictures, and convert the 2D list into a 2D array composed of numbers. The same values of pictures are the same.
4. Traverse the 2-dimensional array, find the object that can be eliminated, and realize the algorithm:
Problems encountered in the implementation process
Picture cutting
im = image.crop((left,top,right,bottom))
//image.crop Parameter is 1 List or tuple, in the order of (left,top,right,bottom)
Find the game running window
hdwd = win32gui.FindWindow(0,wdname)
# Set to front display
win32gui.SetForegroundWindow(hdwd)
Don't click the window to minimize, it can't pop up after clicking.
Scale the picture and turn it to grayscaleimg1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L')
Image. ANTIALIAS is an anti-aliasing option, and the picture has no burrs.
Get the RGB value of each point in the picture
pi1 = list(img1.getdata())
Each element of the list is a 3-digit value, which represents the RGB value of this point. The list pi1 has 400 elements. (Because the picture is 20*20)
Mouse click eliminationPyMouse. click () This method is double-clicked by default and changed to PyMouse. press () or PyMouse. release ()
Judge the similarity of pictures Hamming distance, average hash
def compare_img(self,im1,im2):
img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L')
img2 = im2.resize((20, 20), Image.ANTIALIAS).convert('L')
pi1 = list(img1.getdata())
pi2 = list(img2.getdata())
avg1 = sum(pi1) / len(pi1)
avg2 = sum(pi2) / len(pi2)
hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1))
hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2))
match = 0
for i in range(len(hash1)):
if hash1[i] != hash2[i]:
match += 1
# match = sum(map(operator.ne, hash1, hash2))
# match The smaller the value, the higher the similarity
return match
Calculating histogram
from PIL import Image
# Convert a picture to RGB
def make_regalur_image(img, size=(8, 8)):
gray_image = img.resize(size).convert('RGB')
return gray_image
# Calculating histogram
def hist_similar(lh, rh):
assert len(lh) == len(rh)
hist = sum(1 - (0 if l == r else float(abs(l - r)) / max(l, r)) for l, r in zip(lh, rh)) / len(lh)
return hist
# Calculate similarity
def calc_similar(li, ri):
calc_sim = hist_similar(li.histogram(), ri.histogram())
return calc_sim
if __name__ == '__main__':
image1 = Image.open('1-10.jpg')
image1 = make_regalur_image(image1)
image2 = Image.open('2-11.jpg')
image2 = make_regalur_image(image2)
print(" The similarity between pictures is ", calc_similar(image1, image2))
# Value in [0,1] The larger the value, the higher the similarity
Cosine similarity of pictures
from PIL import Image
from numpy import average, dot, linalg
# Unify pictures 1 Chemical treatment
def get_thum(image, size=(64, 64), greyscale=False):
# Utilization image Reset the image size , Image.ANTIALIAS For high quality
image = image.resize(size, Image.ANTIALIAS)
if greyscale:
# Convert a picture to L Mode, which is a gray image, and each pixel uses 8 A bit Denote
image = image.convert('L')
return image
# Calculate the cosine distance of the picture
def image_similarity_vectors_via_numpy(image1, image2):
image1 = get_thum(image1)
image2 = get_thum(image2)
images = [image1, image2]
vectors = []
norms = []
for image in images:
vector = []
for pixel_tuple in image.getdata():
vector.append(average(pixel_tuple))
vectors.append(vector)
# linalg=linear (Linear) +algebra (Algebra), norm The norm is represented
# Find the norm of a picture? ?
norms.append(linalg.norm(vector, 2))
a, b = vectors
a_norm, b_norm = norms
# dot Returns the dot product, and the 2 Dimensional array (matrix) for calculation
res = dot(a / a_norm, b / b_norm)
return res
if __name__ == '__main__':
image1 = Image.open('1-9.jpg')
image2 = Image.open('8-6.jpg')
cosin = image_similarity_vectors_via_numpy(image1, image2)
print(' Cosine similarity of pictures ', cosin)
# Value in [0,1] The larger the value, the higher the similarity , The calculation amount is large and the efficiency is low
Complete code
import win32gui
import time
from PIL import ImageGrab , Image
import numpy as np
from pymouse import PyMouse
class GameAuxiliaries(object):
def __init__(self):
self.wdname = r' Pet Lianliankan Classic Edition 2, Pet Lianliankan Classic Edition 2 Games ,4399 Games www.4399.com - Google Chrome'
# self.wdname = r'main.swf - PotPlayer'
self.image_list = {}
self.m = PyMouse()
def find_game_wd(self,wdname):
# Get the window handle
hdwd = win32gui.FindWindow(0,wdname)
# Set to front display
win32gui.SetForegroundWindow(hdwd)
time.sleep(1)
def get_img(self):
image = ImageGrab.grab((417, 289, 884, 600))
# image = ImageGrab.grab((417, 257, 885, 569))
image.save('1.jpg','JPEG')
for x in range(1,9):
self.image_list[x] = {}
for y in range(1,13):
top = (x - 1) * 38 + (x-2)
left =(y - 1) * 38 +(y-2)
right = y * 38 + (y-1)
bottom = x * 38 +(x -1)
if top < 0:
top = 0
if left < 0 :
left = 0
im_temp = image.crop((left,top,right,bottom))
im = im_temp.crop((1,1,37,37))
im.save('{}-{}.jpg'.format(x,y))
self.image_list[x][y]=im
# Determine whether the two pictures are the same. Hamming distance, average hash
def compare_img(self,im1,im2):
img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L')
img2 = im2.resize((20, 20), Image.ANTIALIAS).convert('L')
pi1 = list(img1.getdata())
pi2 = list(img2.getdata())
avg1 = sum(pi1) / len(pi1)
avg2 = sum(pi2) / len(pi2)
hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1))
hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2))
match = 0
for i in range(len(hash1)):
if hash1[i] != hash2[i]:
match += 1
# match = sum(map(operator.ne, hash1, hash2))
# match The smaller the value, the higher the similarity
return match
# Convert a picture matrix into a digital matrix
def create_array(self):
array = np.zeros((10,14),dtype=np.int32)
img_type_list = []
for row in range(1,len(self.image_list)+1):
for col in range(1,len(self.image_list[1])+1):
# im = Image.open('{}-{}.jpg'.format(row,col))
im = self.image_list[row][col]
for img in img_type_list:
match = self.compare_img(im,img)
# match = test2.image_similarity_vectors_via_numpy(im,img)
if match <15:
array[row][col] = img_type_list.index(img) +1
break
else:
img_type_list.append(im)
array[row][col] = len(img_type_list)
return array
def row_zero(self,x1,y1,x2,y2,array):
''' Icons in the middle of the same picture are all empty '''
if x1 == x2:
min_y = min(y1,y2)
max_y = max(y1,y2)
if max_y - min_y == 1:
return True
for y in range(min_y+1,max_y):
if array[x1][y] != 0 :
return False
return True
else:
return False
def col_zero(self,x1,y1,x2,y2,array):
''' Same picture, same column '''
if y1 == y2:
min_x = min(x1,x2)
max_x = max(x1,x2)
if max_x - min_x == 1:
return True
for x in range(min_x+1,max_x):
if array[x][y1] != 0 :
return False
return True
else:
return False
def two_line(self,x1,y1,x2,y2,array):
''' Connect two lines and turn 1 Times '''
for row in range(1,9):
for col in range(1,13):
if row == x1 and col == y2 and array[row][col]==0 and self.row_zero(x1,y1,row,col,array) and self.col_zero(x2,y2,row,col,array):
return True
if row == x2 and col == y1 and array[row][col]==0 and self.row_zero(x2,y2,row,col,array) and self.col_zero(x1,y1,row,col,array):
return True
return False
def three_line(self,x1,y1,x2,y2,array):
'''3 Connect lines and turn twice '''
for row1 in range(10):
for col1 in range(14):
for row2 in range(10):
for col2 in range(14):
if array[row1][col1] == array[row2][col2] == 0 and self.row_zero(x1,y1,row1,col1,array) and self.row_zero(x2,y2,row2,col2,array) and self.col_zero(row1,col1,row2,col2,array):
return True
if array[row1][col1] == array[row2][col2] == 0 and self.col_zero(x1,y1,row1,col1,array) and self.col_zero(x2,y2,row2,col2,array) and self.row_zero(row1,col1,row2,col2,array):
return True
if array[row1][col1] == array[row2][col2] == 0 and self.row_zero(x2,y2,row1,col1,array) and self.row_zero(x1,y1,row2,col2,array) and self.col_zero(row1,col1,row2,col2,array):
return True
if array[row1][col1] == array[row2][col2] == 0 and self.col_zero(x2,y2,row1,col1,array) and self.col_zero(x1,y1,row2,col2,array) and self.row_zero(row1,col1,row2,col2,array):
return True
return False
def mouse_click(self,x,y):
top = (x - 1) * 38 + (x - 2)
left = (y - 1) * 38 + (y - 2)
right = y * 38 + (y - 1)
bottom = x * 38 + (x - 1)
if top < 0:
top = 0
if left < 0:
left = 0
self.m.press(int(417+(left+right)/2) ,int(289+(top+bottom)/2) )
def find_same_img(self,array):
for x1 in range(1,9):
for y1 in range(1,13):
if array[x1][y1] == 0:
continue
for x2 in range(1,9):
for y2 in range(1,13):
if x1==x2 and y1 == y2:
continue
if array[x2][y2] == 0 :
continue
if array[x1][y1] != array[x2][y2] :
continue
if array[x1][y1] ==array[x2][y2] and (self.row_zero(x1,y1,x2,y2,array) or self.col_zero(x1,y1,x2,y2,array) or self.two_line(x1,y1,x2,y2,array) or self.three_line(x1,y1,x2,y2,array)):
print(" It can be eliminated! x{}y{} And x{}y{}".format(x1,y1,x2,y2))
self.mouse_click(x1,y1)
time.sleep(0.1)
self.mouse_click(x2,y2)
time.sleep(0.1)
array[x1][y1]=array[x2][y2]=0
def run(self):
# Find the game running window
self.find_game_wd(self.wdname)
# Screenshot, cut into small icons
self.get_img()
# Convert a picture matrix into a digital matrix
array = self.create_array()
print(array)
# Traverse the matrix, find the items that can be eliminated, and click Eliminate
for i in range(10):
self.find_same_img(array)
print(array)
if __name__ == '__main__':
ga = GameAuxiliaries()
ga.run()
Summarize
In fact, the program can't fully realize the auxiliary function, mainly because the better rules can't be found when cutting pictures, which makes it difficult to identify pictures. The scale and judgment threshold can't find a balance point. If the threshold is too large, different icons will be identified as the same, while the threshold is too small, and the same icons will be judged as different.
For more wonderful articles about python games, please click to view the following topics:
python Tetris Game Collection
python Classic Games Summary
python WeChat Jump 1 Jump Game Collection