icon.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import cv2
  2. import numpy as np
  3. import requests
  4. import random
  5. from typing import List, Dict, Union, Optional, Any
  6. class IconSolver:
  7. # Mapping of icon filenames to directions
  8. ICON_MAPPING = {
  9. '8da090c135ff029f3b5e19f4c44f73c8.png': 'u',
  10. 'cb0eaa639b2117a69a81af3d8c1496a1.png': 'd',
  11. '315ce8665e781dabcd1eb09d3e604803.png': 'l',
  12. '38bd9dda695098c7dfad74c921923a7d.png': 'lu',
  13. '502e51dbabf411beba2dcd55fd38ebbd.png': 'ld',
  14. '2b2387f566f6a03ed594d4d7cfda471f.png': 'r',
  15. '78dc29045d587ad054c7353732df53c5.png': 'ru',
  16. '23ef93e6b0e0df0e15b66667c99a5fb4.png': 'rd'
  17. }
  18. def __init__(self, imgs: str, ques: List[str]):
  19. self.imgs = self.load_image(f'https://static.geetest.com/{imgs}')
  20. self.ques = ques
  21. @staticmethod
  22. def test() -> None:
  23. """Test method for the IconSolver class."""
  24. identifier = IconSolver(
  25. imgs="captcha_v4/policy/87d2c0d959/icon/163935/2025-04-20T17/3f99716d17324c9ba3eec402121eb1d9.jpg",
  26. ques=[
  27. "nerualpic/original_icon_pic/icon_20201215/315ce8665e781dabcd1eb09d3e604803.png",
  28. "nerualpic/original_icon_pic/icon_20201215/38bd9dda695098c7dfad74c921923a7d.png",
  29. "nerualpic/original_icon_pic/icon_20201215/cb0eaa639b2117a69a81af3d8c1496a1.png"
  30. ]
  31. )
  32. result = identifier.find_icon_position()
  33. print(f"Result: {result}")
  34. @staticmethod
  35. def load_image(url: str) -> bytes:
  36. """Load image from URL and return as bytes."""
  37. response = requests.get(url, timeout=10)
  38. response.raise_for_status() # Raise exception for bad status codes
  39. return response.content
  40. def _get_directions(self) -> List[Dict[str, Any]]:
  41. """Extract directions from question icons using the predefined mapping."""
  42. return [{'direction': self.ICON_MAPPING.get(q.split('/')[-1], '')} for q in self.ques]
  43. def _process_bbox(self, bbox: List[int], im: np.ndarray) -> Optional[Dict[str, Union[str, List[float]]]]:
  44. """Process a single bounding box and return direction and coordinates if matched."""
  45. from .dddd_server import dddd_service
  46. x1, y1, x2, y2 = bbox
  47. img = im[y1:y2, x1:x2]
  48. _, img_bytes = cv2.imencode(".png", img)
  49. res = dddd_service.classification(img_bytes.tobytes())
  50. res = res.split('_')[1]
  51. return res if res in self.ICON_MAPPING.values() else None
  52. def find_icon_position(self) -> List[List[float]]:
  53. """
  54. Find icon positions based on the question directions.
  55. Returns a list of coordinates for each required direction.
  56. """
  57. from .dddd_server import dddd_service
  58. bboxes = dddd_service.detection(self.imgs)
  59. im = cv2.imdecode(np.frombuffer(self.imgs, dtype=np.uint8), cv2.IMREAD_COLOR)
  60. box_directions = self._get_directions()
  61. unused_boxes = []
  62. results = []
  63. for bbox in bboxes:
  64. processed = self._process_bbox(bbox, im)
  65. if not processed:
  66. continue
  67. x1, y1, x2, y2 = bbox
  68. center = [(x1 + (x2 - x1) / 2) * 33, (y1 + (y2 - y1) / 2) * 49]
  69. # Try to match with required directions
  70. matched = False
  71. for boxd in box_directions:
  72. if boxd['direction'] == processed and 'bbox' not in boxd:
  73. boxd['bbox'] = center
  74. matched = True
  75. break
  76. if not matched:
  77. unused_boxes.append(center)
  78. # Prepare results, using unused boxes if needed
  79. for boxd in box_directions:
  80. if 'bbox' in boxd:
  81. results.append(boxd['bbox'])
  82. elif unused_boxes:
  83. results.append(unused_boxes.pop(random.randint(0, len(unused_boxes) - 1)))
  84. return results
  85. if __name__ == '__main__':
  86. IconSolver.test()