Improving my code for image recognition - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code Review (https://python-forum.io/forum-46.html) +--- Thread: Improving my code for image recognition (/thread-25264.html) |
Improving my code for image recognition - SheeppOSU - Mar-25-2020 I was trying to make a bot that would work through image detection. So I did it, and it works, but I came to ask for suggestion on how I can improve my code to make things run more smoothly and efficiently. There's one main function, two utility functions, and then one more function for testing its efficiency. Here's the code: from PIL import ImageGrab import time, cv2, random #Pre-sets FileNames = {"Main" : "Screenshot.png", "Level" : "Level.png", "Refresh" : "Refresh.png", "StartExercise" : "StartExercise.png", "Test" : "TestCapture.png"} #Util Functions def UpdatedImage(imageName, coords=None): ImageGrab.grab(coords).save(imageName, "PNG") return cv2.imread(imageName) def CheckPixels(pixel1, pixel2): if pixel1[0] == pixel2[0] and pixel1[1] == pixel2[1] and pixel1[2] == pixel2[2]: return True return False def CheckImages(originalImage, comparisonImage): #This function finds a pixel that matches the first pixel of the comparison Picture and then checks all the pixels around it until it has either identified it to be matching or not matching StartingPixel = comparisonImage[0][0] for row in range(0, len(originalImage)): pixelCount = -1 if row+len(comparisonImage) > len(originalImage): break for pixel in originalImage[row]: pixelCount += 1 if pixelCount+len(comparisonImage[0]) > len(originalImage[0]): break if CheckPixels(pixel, StartingPixel): matching = True columnOffset = 0 rowOffset = 0 while matching: while matching and columnOffset < len(comparisonImage[0])-1 and rowOffset < len(comparisonImage)-1: columnOffset += 1 if not CheckPixels(comparisonImage[rowOffset][columnOffset], originalImage[row+rowOffset][pixelCount+columnOffset]): matching = False if columnOffset == len(comparisonImage[0])-1 and matching: rowOffset += 1 offset = 0 if rowOffset == len(comparisonImage)-1: return True, (pixelCount-columnOffset, row-rowOffset) return False, None def Testrun(accuracy): TimeDatabase = [] FalseCount = 0 for x in range(0, accuracy): print("Preparing images...") ScreenshotData = UpdatedImage(FileNames["Main"]) TestImageData = UpdatedImage(FileNames["Test"], (random.randint(0, 525), random.randint(0, 325), random.randint(526, 1050), random.randint(325, 650))) print("Testing commenced...") startingTime = time.time() success, _ = CheckImages(ScreenshotData, TestImageData) if not success: FalseCount += 1 totalTime = time.time()-startingTime TimeDatabase.append(totalTime) print("Testing number %s was a success: %s\ntotal time applied: %s\n" %(x+1, success, totalTime)) AverageTime = 0 for t in TimeDatabase: AverageTime += t AverageTime /= len(TimeDatabase) MinTime = min(TimeDatabase) MaxTime = max(TimeDatabase) print("Testing is now complete. The average time for each run was %s\nThe minimum time was %s\nThe maximum time was %s\n%s tests were found to be false" %(AverageTime, MinTime, MaxTime, FalseCount)) if __name__ == "__main__": #Exercise() Testrun(100)I ran it on my background which is colorful and probably made it easier for the program. The background was also changing every ten seconds hence the 6 failed tests. This is the output (Not including the individual prints of each test). One last thing, are there any efficient methods to recognizing photos that are enlarged from the original? For example, if I took a screenshot, snipped a part of it, enlarged that part a little bit, and the bot could still recognize the picture from the screenshot.Thanks in advance for any help with this. RE: Improving my code for image recognition - ndc85430 - Mar-26-2020 I've not looked at most of the code, but a couple of quick things I noticed: (Mar-25-2020, 07:28 AM)SheeppOSU Wrote:def CheckPixels(pixel1, pixel2): if pixel1[0] == pixel2[0] and pixel1[1] == pixel2[1] and pixel1[2] == pixel2[2]: return True return False 1. The name of the function could be more descriptive. What does "check" really mean here? 2. The if is unnecessary. You have an expression that evaluates to True or False , so you could just return its value:def CheckPixels(pixel1, pixel2): return pixel1[0] == pixel2[0] and pixel1[1] == pixel2[1] and pixel1[2] == pixel2[2]: About CheckImages :1. Does it need to return two values? You don't seem to use the second one at all (it's thrown away on line 58). 2. The function is quite long and complex. That makes it difficult to understand (and test!) and is probably a sign that it does too much. It should ideally be broken down into smaller functions. 3. Naming again! If you have to write a comment to describe what the function does, it's a sign that the name isn't descriptive enough (see Robert C. Martin's Clean Code for more on this kind of thing). RE: Improving my code for image recognition - SheeppOSU - Mar-26-2020 Thx for the advice. I'll tweak my code a bit to make it better. The second value is actually for some other functions that I'll make in the future. RE: Improving my code for image recognition - ndc85430 - Mar-28-2020 Also, a note on style: names of functions and variables are usually written in snake case (e.g. some_variable or my_function ) and camel case reserved for class names. See PEP 8 for more.
|