Python Forum
Improving my code for image recognition
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Improving my code for image recognition
#1
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).
Output:
Testing is now complete. The average time for each run was 0.33153117656707765 The minimum time was 0.006017446517944336 The maximum time was 5.9415600299835205 6 tests were found to be false
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.
Reply
#2
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).
Reply
#3
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.
Reply
#4
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Optimization of image correction code Techmokid 0 1,856 Mar-21-2020, 12:25 PM
Last Post: Techmokid

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020