I'm using OpenCV to detect images in real-time. This is working with single images. I'm trying to update the script to work with multiple images at once with the end goal to be to detect a few different elements on the screen at once and draw rectangles around them while returning the centre points of the images for use elsewhere.
I've gotten as far as passing the images in from my main.py
file and initiating the search.
# load source images
source_images = glob.glob(r'C:\\\\\\\*.jpg')
# perform the search
search = Search(source_images)
I can't seem to pass loaded_images
into my find
function. I've tried defining loaded_images
in the Class properties and within the constructor but neither work and give me the error NameError: name 'loaded_images' is not defined
class Search:
# properties
needle_img = None
needle_w = 0
needle_h = 0
method = None
# empty list to store the source images
#loaded_images = [] <-------------------------------------------------
# constructor
def __init__(self, source_images, method=cv.TM_CCOEFF_NORMED):
# Set the method we're using when we load the image
self.method = method
# empty list to store the source images
# loaded_images = [] <-------------------------------------------------
# load the needle image into loaded_iamges array
for img in source_images:
self.needle_img = cv.imread(img, cv.IMREAD_UNCHANGED)
loaded_images.append(self.needle_img)
return self.loaded_images <--------------------------------
def find(self, haystack_img, threshold=0.5, debug_mode=None):
for img in loaded_images:
# Save the dimensions of the needle images
self.needle_w = self.needle_img.shape[1]
self.needle_h = self.needle_img.shape[0]
# run the OpenCV algorithm
result = cv.matchTemplate(haystack_img, self.needle_img, self.method)
I also wrote this next code segment that matches multiple images on a screenshot rather than a real-time image to try and figure out what I was doing wrong. It's helped me get this far but I am now stuck.
# load source images
source_images = glob.glob(r'C:\\\\\\\*.jpg')
# empty list to store the source images
loaded_images = []
for img in source_images:
needle_img = cv.imread(img, 0)
loaded_images.append(needle_img)
haystack_img = cv.imread(r'C:\\\\\\both.jpg')
haystack_img = cv.cvtColor(haystack_img, cv.COLOR_BGR2GRAY)
#loop for matching
for needles in loaded_images:
#save the dimensions of the needle images
(tH, tW) = needles.shape[:2]
result = cv.matchTemplate(haystack_img, needles, cv.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
top_left = max_loc
bottom_right = (top_left[0] + tW, top_left[1] + tH)
cv.rectangle(haystack_img, top_left, bottom_right, 255, 2)
cv.imshow('Result', haystack_img)
cv.waitKey(0)
Either pass loaded images directly to find:
class Search:
def __init__(self, source_images, method=cv.TM_CCOEFF_NORMED):
# Set the method we're using when we load the image
self.method = method
def find(self, haystack_img, loaded_images, threshold=0.5, debug_mode=None):
for img in loaded_images:
# Save the dimensions of the needle images
self.needle_w = self.needle_img.shape[1]
self.needle_h = self.needle_img.shape[0]
# you are overwriting the same needle_w and needle_h variable over and over again in a loop...
# run the OpenCV algorithm
result = cv.matchTemplate(haystack_img, self.needle_img, self.method)
Or store loaded images in field:
class Search:
def __init__(self, source_images, method=cv.TM_CCOEFF_NORMED):
# Set the method we're using when we load the image
self.method = method
self.loaded_images = []
# load the needle image into loaded_iamges array
for img in source_images:
needle_img = cv.imread(img, cv.IMREAD_UNCHANGED)
self.loaded_images.append(needle_img)
def find(self, haystack_img, threshold=0.5, debug_mode=None):
for img in self.loaded_images:
# Save the dimensions of the needle images
self.needle_w = self.needle_img.shape[1]
self.needle_h = self.needle_img.shape[0]
# you are overwriting the same needle_w and needle_h variable over and over again in a loop...
# run the OpenCV algorithm
result = cv.matchTemplate(haystack_img, self.needle_img, self.method)
In general you need to learn about scopes and difference between class and instance variables. Also I don't see here why you would need class when you would probably only have one instance of it, so maybe read about OOP in general.
You have two options in this case. Either define load_images
as an instance variable with self.
. But then you should call it as self.loaded_images
everywhere within the class.
class Search:
self.loaded_images = []
for ...
self.loaded_images.append(...)
Or, you can define as a parameter in the function.
def find(self, loaded_images, haystack_img, threshold=0.5, debug_mode=None):
Then you can leave the definition of load_images
as it is currently in __init__
method (uncomment load_images=[ ]
), but be sure that you call the find
function with your load_images
where you had "loaded" images.
It is completely up to you how to structure your variable.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.