locate.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import cv2
  2. import numpy as np
  3. def non_max_suppression(boxes, overlapThresh):
  4. if len(boxes) == 0:
  5. return []
  6. # Convert to float
  7. boxes = np.array(boxes, dtype="float")
  8. # Initialize the list of picked indexes
  9. pick = []
  10. # Grab the coordinates of the bounding boxes
  11. x1 = boxes[:, 0]
  12. y1 = boxes[:, 1]
  13. x2 = boxes[:, 2]
  14. y2 = boxes[:, 3]
  15. # Compute the area of the bounding boxes and sort by bottom-right y-coordinate
  16. area = (x2 - x1 + 1) * (y2 - y1 + 1)
  17. idxs = np.argsort(y2)
  18. # Keep looping while some indexes still remain in the indexes list
  19. while len(idxs) > 0:
  20. # Grab the last index in the indexes list and add the index value to the list of picked indexes
  21. last = len(idxs) - 1
  22. i = idxs[last]
  23. pick.append(i)
  24. # Find the largest (x, y) coordinates for the start of the bounding box and the smallest (x, y)
  25. # coordinates for the end of the bounding box
  26. xx1 = np.maximum(x1[i], x1[idxs[:last]])
  27. yy1 = np.maximum(y1[i], y1[idxs[:last]])
  28. xx2 = np.minimum(x2[i], x2[idxs[:last]])
  29. yy2 = np.minimum(y2[i], y2[idxs[:last]])
  30. # Compute the width and height of the bounding box
  31. w = np.maximum(0, xx2 - xx1 + 1)
  32. h = np.maximum(0, yy2 - yy1 + 1)
  33. # Compute the ratio of overlap
  34. overlap = (w * h) / area[idxs[:last]]
  35. # Delete all indexes from the index list that have overlap greater than the threshold
  36. idxs = np.delete(
  37. idxs, np.concatenate(([last], np.where(overlap > overlapThresh)[0]))
  38. )
  39. # Return only the bounding boxes that were picked
  40. return boxes[pick].astype("int")
  41. # Load images
  42. target_image = cv2.imread("test/20240108_224218.jpg")
  43. template_image = cv2.imread("templates/dungeon/attack.png")
  44. h, w = template_image.shape[:-1]
  45. # Template matching
  46. result = cv2.matchTemplate(target_image, template_image, cv2.TM_CCOEFF_NORMED)
  47. # Define a threshold
  48. threshold = 0.9 # Adjust this threshold based on your requirements
  49. # Finding all locations where match exceeds threshold
  50. locations = np.where(result >= threshold)
  51. locations = list(zip(*locations[::-1]))
  52. # Create list of rectangles
  53. rectangles = [(*loc, loc[0] + w, loc[1] + h) for loc in locations]
  54. # Apply non-maximum suppression to remove overlaps
  55. rectangles = non_max_suppression(rectangles, 0.3)
  56. # Draw rectangles around matches
  57. for startX, startY, endX, endY in rectangles:
  58. cv2.rectangle(target_image, (startX, startY), (endX, endY), (0, 255, 0), 2)
  59. # Print the coordinates of the rectangle
  60. centerX = round(startX + (endX - startX) / 2)
  61. centerY = round(startY + (endY - startY) / 2)
  62. print(f"center coordinates: {centerX}/{centerY}")
  63. # Display the result
  64. cv2.imshow("Matched Results", target_image)
  65. cv2.waitKey(0)
  66. cv2.destroyAllWindows()