Python - CV2

From Torben's Wiki
(Redirected from Python - OpenCV)

Image Regocnition Using CV2 / OpenCV

Basics

import cv2  # c:\Python\Scripts\pip install opencv-python

# Read Template Image
img_template = cv2.imread('templates/template.png')
# Show Image
cv2.imshow("Template ", img_template ) ; cv2.waitKey(0)

Modify Images

# convert image to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# detect edges 
img_edged = cv2.Canny(img_gray, 50, 200)

Use Screenshots

def takeScreenshot():
   import pyautogui # c:\Python\Scripts\pip install pyautogui
   # ...
   # Attention: supports only screenshots of monitor#1
   screenshot = pyautogui.screenshot()
   # screenshot = pyautogui.screenshot(region=(screenshotX,screenshotY, screenshotW, screenshotH))
   # Convert to numpy array
   screenshot = np.array(screenshot) 
   # Convert RGB to BGR 
   screenshot = screenshot[:, :, ::-1].copy()
   return screenshot

Match Images

# often gray scaled images are used for faster processing
# many people use edge representation instead of original images
# convert image to grayscale
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# detect edges 
img_edged = cv2.Canny(img_gray, 50, 200)
def matchImages(img_edged, template_edged, threshold = 0.8) :
   x = -1
   y = -1
   # result = cv2.matchTemplate(screenshotGray, template1, cv2.TM_CCOEFF)
   result = cv2.matchTemplate(screenshot, template, cv2.TM_CCOEFF_NORMED)
   (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)  

   
   loc = np.where( result >= threshold)
   
   # Size of template
   (tH, tW) = template.shape[:2]
   
   # draw a bounding box around the detected region
   clone = np.dstack([screenshot, screenshot, screenshot])
   numHits = 0
   for pt in zip(*loc[::-1]):
       numHits += 1
       # print (pt[0] , " , ", pt[1] )
       if (numHits == 1):
           # return coordinates of 1st match
           x = int(pt[0] + tW/2)
           y = int(pt[1] + tH/2)
       cv2.rectangle(clone, pt, (pt[0] + tW, pt[1] + tH), (0,0,255), 2)
   
   if (numHits > 0):
       print (str(numHits) + " Treffer")
   cv2.imshow(str(numHits) + " Treffer", clone) ; cv2.waitKey(0)    
   return x,y

Match Images Exactly

(usind numpy, not CV2)

def matchImagesExact(im, tpl):
# https://stackoverflow.com/questions/29663764/determine-if-an-image-exists-within-a-larger-image-and-if-so-find-it-using-py
   im = np.atleast_3d(im)
   tpl = np.atleast_3d(tpl)
   H, W, D = im.shape[:3]
   h, w = tpl.shape[:2]

   # Integral image and template sum per channel
   sat = im.cumsum(1).cumsum(0)
   tplsum = np.array([tpl[:, :, i].sum() for i in range(D)])

   # Calculate lookup table for all the possible windows
   iA, iB, iC, iD = sat[:-h, :-w], sat[:-h, w:], sat[h:, :-w], sat[h:, w:] 
   lookup = iD - iB - iC + iA
   # Possible matches
   possible_match = np.where(np.logical_and.reduce([lookup[..., i] == tplsum[i] for i in range(D)]))

   # Find exact match
   for y, x in zip(*possible_match):
       if np.all(im[y+1:y+h+1, x+1:x+w+1] == tpl):
           return (x+1+w/2 , y+1+h/2)
   return -1,-1

Color Filter

# Convert RGB/BGR to HSV representation of image
# https://docs.opencv.org/3.2.0/df/d9d/tutorial_py_colorspaces.html
green = np.uint8([[[102,255,102 ]]]) # BGR obtained from Gimp
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
# print (hsv_green)
# 102,255,102 -> 60 153 255
# Now you take [H-10, 100,100] and [H+10, 255, 255] as lower bound and upper bound respectively.
lower_green = np.array([50,100,100])
upper_green = np.array([70,255,255])

# Load Image
image = cv2.imread('image.png')
# Convert BGR to HSV
img_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# Threshold the HSV image to get only green colors
img_mask = cv2.inRange(img_hsv, lower_green, upper_green)
# Bitwise-AND mask and original image
img_res = cv2.bitwise_and(image,image, mask=img_mask)
# invert Mask
img_mask_inv = cv2.bitwise_not(img_mask)

# Show results
cv2.imshow('image',image)
cv2.imshow('mask',img_mask)
cv2.imshow('img_mask_inv',img_mask_inv)
cv2.imshow('res',img_res)
cv2.waitKey(0)