prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Image anonymization is slow
  Hi,
  
  First of all, thank you guys for making this awesome project :)
  
  I wanted to ask if there are any ways to improve image anonymization performance. I'm using Presidio as a python package and it takes about 5~ seconds to process pretty small images. I'm using the example code from the Presidio docs.
  
  </issue>
  <code>
  [start of presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py]
  1 from typing import List
  2 
  3 from presidio_analyzer import AnalyzerEngine
  4 from presidio_analyzer import RecognizerResult
  5 from presidio_image_redactor.entities.image_recognizer_result import (
  6     ImageRecognizerResult,
  7 )
  8 from presidio_image_redactor.ocr import OCR
  9 
  10 
  11 class ImageAnalyzerEngine:
  12     """ImageAnalyzerEngine class."""
  13 
  14     def analyze(self, image: object, **kwargs) -> List[ImageRecognizerResult]:
  15         """Analyse method to analyse the given image.
  16 
  17         :param image: PIL Image/numpy array or file path(str) to be processed
  18 
  19         :return: list of the extract entities with image bounding boxes
  20         """
  21         ocr_result = OCR().perform_ocr(image)
  22         text = OCR().get_text_from_ocr_dict(ocr_result)
  23 
  24         analyzer = AnalyzerEngine()
  25         analyzer_result = analyzer.analyze(text=text, language="en", **kwargs)
  26         bboxes = self.map_analyzer_results_to_bounding_boxes(
  27             analyzer_result, ocr_result, text
  28         )
  29         return bboxes
  30 
  31     @staticmethod
  32     def map_analyzer_results_to_bounding_boxes(
  33         text_analyzer_results: List[RecognizerResult], ocr_result: dict, text: str
  34     ) -> List[ImageRecognizerResult]:
  35         """Map extracted PII entities to image bounding boxes.
  36 
  37         Matching is based on the position of the recognized entity from analyzer
  38         and word (in ocr dict) in the text.
  39 
  40         :param text_analyzer_results: PII entities recognized by presidio analyzer
  41         :param ocr_result: dict results with words and bboxes from OCR
  42         :param text: text the results are based on
  43 
  44         return: list of extracted entities with image bounding boxes
  45         """
  46         if (not ocr_result) or (not text_analyzer_results):
  47             return []
  48 
  49         bboxes = []
  50         proc_indexes = 0
  51         indexes = len(text_analyzer_results)
  52 
  53         pos = 0
  54         iter_ocr = enumerate(ocr_result["text"])
  55         for index, word in iter_ocr:
  56             if not word:
  57                 pos += 1
  58             else:
  59                 for element in text_analyzer_results:
  60                     text_element = text[element.start : element.end]
  61                     # check position and text of ocr word matches recognized entity
  62                     if (
  63                         max(pos, element.start) < min(element.end, pos + len(word))
  64                     ) and ((text_element in word) or (word in text_element)):
  65                         bboxes.append(
  66                             ImageRecognizerResult(
  67                                 element.entity_type,
  68                                 element.start,
  69                                 element.end,
  70                                 element.score,
  71                                 ocr_result["left"][index],
  72                                 ocr_result["top"][index],
  73                                 ocr_result["width"][index],
  74                                 ocr_result["height"][index],
  75                             )
  76                         )
  77 
  78                         # add bounding boxes for all words in ocr dict
  79                         # contained within the text of recognized entity
  80                         # based on relative position in the full text
  81                         while pos + len(word) < element.end:
  82                             index, word = next(iter_ocr)
  83                             if word:
  84                                 bboxes.append(
  85                                     ImageRecognizerResult(
  86                                         element.entity_type,
  87                                         element.start,
  88                                         element.end,
  89                                         element.score,
  90                                         ocr_result["left"][index],
  91                                         ocr_result["top"][index],
  92                                         ocr_result["width"][index],
  93                                         ocr_result["height"][index],
  94                                     )
  95                                 )
  96                             pos += len(word) + 1
  97                         proc_indexes += 1
  98 
  99                 if proc_indexes == indexes:
  100                     break
  101                 pos += len(word) + 1
  102 
  103         return bboxes
  104
  [end of presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py
  --- a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py
  +++ b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py
  @@ -9,7 +9,16 @@
   
   
   class ImageAnalyzerEngine:
  -    """ImageAnalyzerEngine class."""
  +    """ImageAnalyzerEngine class.
  +
  +    :param analyzer_engine: The Presidio AnalyzerEngine instance
  +        to be used to detect PII in text.
  +    """
  +
  +    def __init__(self, analyzer_engine: AnalyzerEngine = None):
  +        if not analyzer_engine:
  +            analyzer_engine = AnalyzerEngine()
  +        self.analyzer_engine = analyzer_engine
   
       def analyze(self, image: object, **kwargs) -> List[ImageRecognizerResult]:
           """Analyse method to analyse the given image.
  @@ -21,8 +30,8 @@
           ocr_result = OCR().perform_ocr(image)
           text = OCR().get_text_from_ocr_dict(ocr_result)
   
  -        analyzer = AnalyzerEngine()
  -        analyzer_result = analyzer.analyze(text=text, language="en", **kwargs)
  +        analyzer_result = self.analyzer_engine.analyze(
  +            text=text, language="en", **kwargs)
           bboxes = self.map_analyzer_results_to_bounding_boxes(
               analyzer_result, ocr_result, text
           )
  
verification_info: {"golden_diff": "diff --git a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py\n--- a/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py\n+++ b/presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py\n@@ -9,7 +9,16 @@\n \n \n class ImageAnalyzerEngine:\n-    \"\"\"ImageAnalyzerEngine class.\"\"\"\n+    \"\"\"ImageAnalyzerEngine class.\n+\n+    :param analyzer_engine: The Presidio AnalyzerEngine instance\n+        to be used to detect PII in text.\n+    \"\"\"\n+\n+    def __init__(self, analyzer_engine: AnalyzerEngine = None):\n+        if not analyzer_engine:\n+            analyzer_engine = AnalyzerEngine()\n+        self.analyzer_engine = analyzer_engine\n \n     def analyze(self, image: object, **kwargs) -> List[ImageRecognizerResult]:\n         \"\"\"Analyse method to analyse the given image.\n@@ -21,8 +30,8 @@\n         ocr_result = OCR().perform_ocr(image)\n         text = OCR().get_text_from_ocr_dict(ocr_result)\n \n-        analyzer = AnalyzerEngine()\n-        analyzer_result = analyzer.analyze(text=text, language=\"en\", **kwargs)\n+        analyzer_result = self.analyzer_engine.analyze(\n+            text=text, language=\"en\", **kwargs)\n         bboxes = self.map_analyzer_results_to_bounding_boxes(\n             analyzer_result, ocr_result, text\n         )\n", "issue": "Image anonymization is slow\nHi,\r\n\r\nFirst of all, thank you guys for making this awesome project :)\r\n\r\nI wanted to ask if there are any ways to improve image anonymization performance. I'm using Presidio as a python package and it takes about 5~ seconds to process pretty small images. I'm using the example code from the Presidio docs.\n", "before_files": [{"content": "from typing import List\n\nfrom presidio_analyzer import AnalyzerEngine\nfrom presidio_analyzer import RecognizerResult\nfrom presidio_image_redactor.entities.image_recognizer_result import (\n    ImageRecognizerResult,\n)\nfrom presidio_image_redactor.ocr import OCR\n\n\nclass ImageAnalyzerEngine:\n    \"\"\"ImageAnalyzerEngine class.\"\"\"\n\n    def analyze(self, image: object, **kwargs) -> List[ImageRecognizerResult]:\n        \"\"\"Analyse method to analyse the given image.\n\n        :param image: PIL Image/numpy array or file path(str) to be processed\n\n        :return: list of the extract entities with image bounding boxes\n        \"\"\"\n        ocr_result = OCR().perform_ocr(image)\n        text = OCR().get_text_from_ocr_dict(ocr_result)\n\n        analyzer = AnalyzerEngine()\n        analyzer_result = analyzer.analyze(text=text, language=\"en\", **kwargs)\n        bboxes = self.map_analyzer_results_to_bounding_boxes(\n            analyzer_result, ocr_result, text\n        )\n        return bboxes\n\n    @staticmethod\n    def map_analyzer_results_to_bounding_boxes(\n        text_analyzer_results: List[RecognizerResult], ocr_result: dict, text: str\n    ) -> List[ImageRecognizerResult]:\n        \"\"\"Map extracted PII entities to image bounding boxes.\n\n        Matching is based on the position of the recognized entity from analyzer\n        and word (in ocr dict) in the text.\n\n        :param text_analyzer_results: PII entities recognized by presidio analyzer\n        :param ocr_result: dict results with words and bboxes from OCR\n        :param text: text the results are based on\n\n        return: list of extracted entities with image bounding boxes\n        \"\"\"\n        if (not ocr_result) or (not text_analyzer_results):\n            return []\n\n        bboxes = []\n        proc_indexes = 0\n        indexes = len(text_analyzer_results)\n\n        pos = 0\n        iter_ocr = enumerate(ocr_result[\"text\"])\n        for index, word in iter_ocr:\n            if not word:\n                pos += 1\n            else:\n                for element in text_analyzer_results:\n                    text_element = text[element.start : element.end]\n                    # check position and text of ocr word matches recognized entity\n                    if (\n                        max(pos, element.start) < min(element.end, pos + len(word))\n                    ) and ((text_element in word) or (word in text_element)):\n                        bboxes.append(\n                            ImageRecognizerResult(\n                                element.entity_type,\n                                element.start,\n                                element.end,\n                                element.score,\n                                ocr_result[\"left\"][index],\n                                ocr_result[\"top\"][index],\n                                ocr_result[\"width\"][index],\n                                ocr_result[\"height\"][index],\n                            )\n                        )\n\n                        # add bounding boxes for all words in ocr dict\n                        # contained within the text of recognized entity\n                        # based on relative position in the full text\n                        while pos + len(word) < element.end:\n                            index, word = next(iter_ocr)\n                            if word:\n                                bboxes.append(\n                                    ImageRecognizerResult(\n                                        element.entity_type,\n                                        element.start,\n                                        element.end,\n                                        element.score,\n                                        ocr_result[\"left\"][index],\n                                        ocr_result[\"top\"][index],\n                                        ocr_result[\"width\"][index],\n                                        ocr_result[\"height\"][index],\n                                    )\n                                )\n                            pos += len(word) + 1\n                        proc_indexes += 1\n\n                if proc_indexes == indexes:\n                    break\n                pos += len(word) + 1\n\n        return bboxes\n", "path": "presidio-image-redactor/presidio_image_redactor/image_analyzer_engine.py"}]}