55import Levenshtein
66import numpy as np
77from cv2 .typing import MatLike
8- from scipy import fft
98
109from utils import (
1110 BGRA_CHANNEL_COUNT ,
@@ -90,27 +89,40 @@ def compare_template(source: MatLike, capture: MatLike, mask: MatLike | None = N
9089 return 1 - (min_val / max_error )
9190
9291
93- def __cv2_phash (image : MatLike , hash_size : int = 8 , highfreq_factor : int = 4 ):
94- """Implementation copied from https://github.com/JohannesBuchner/imagehash/blob/38005924fe9be17cfed145bbc6d83b09ef8be025/imagehash/__init__.py#L260 .""" # noqa: E501
95- # OpenCV has its own pHash comparison implementation in `cv2.img_hash`,
96- # but it requires contrib/extra modules and is inaccurate
97- # unless we precompute the size with a specific interpolation.
98- # See: https://github.com/opencv/opencv_contrib/issues/3295#issuecomment-1172878684
99- #
100- # pHash = cv2.img_hash.PHash.create()
101- # source = cv2.resize(source, (8, 8), interpolation=cv2.INTER_AREA)
102- # capture = cv2.resize(capture, (8, 8), interpolation=cv2.INTER_AREA)
103- # source_hash = pHash.compute(source)
104- # capture_hash = pHash.compute(capture)
105- # hash_diff = pHash.compare(source_hash, capture_hash)
106-
107- img_size = hash_size * highfreq_factor
108- image = cv2 .cvtColor (image , cv2 .COLOR_BGRA2GRAY )
109- image = cv2 .resize (image , (img_size , img_size ), interpolation = cv2 .INTER_AREA )
110- dct = fft .dct (fft .dct (image , axis = 0 ), axis = 1 )
111- dct_low_frequency = dct [:hash_size , :hash_size ]
112- median = np .median (dct_low_frequency )
113- return dct_low_frequency > median
92+ try :
93+ from scipy import fft
94+
95+ def __cv2_scipy_compute_phash (image : MatLike , hash_size : int , highfreq_factor : int = 4 ):
96+ """Implementation copied from https://github.com/JohannesBuchner/imagehash/blob/38005924fe9be17cfed145bbc6d83b09ef8be025/imagehash/__init__.py#L260 .""" # noqa: E501
97+ img_size = hash_size * highfreq_factor
98+ image = cv2 .cvtColor (image , cv2 .COLOR_BGRA2GRAY )
99+ image = cv2 .resize (image , (img_size , img_size ), interpolation = cv2 .INTER_AREA )
100+ dct = fft .dct (fft .dct (image , axis = 0 ), axis = 1 )
101+ dct_low_frequency = dct [:hash_size , :hash_size ]
102+ median = np .median (dct_low_frequency )
103+ return dct_low_frequency > median
104+
105+ def __cv2_phash (source : MatLike , capture : MatLike , hash_size : int = 8 ): # pyright: ignore[reportRedeclaration]
106+ source_hash = __cv2_scipy_compute_phash (source , hash_size )
107+ capture_hash = __cv2_scipy_compute_phash (capture , hash_size )
108+ hash_diff = np .count_nonzero (source_hash != capture_hash )
109+ return 1 - (hash_diff / 64.0 )
110+
111+ except ModuleNotFoundError :
112+
113+ def __cv2_phash (source : MatLike , capture : MatLike , hash_size : int = 8 ):
114+ # OpenCV has its own pHash comparison implementation in `cv2.img_hash`,
115+ # but it requires contrib/extra modules and is inaccurate
116+ # unless we precompute the size with a specific interpolation.
117+ # See: https://github.com/opencv/opencv_contrib/issues/3295#issuecomment-1172878684
118+ #
119+ phash = cv2 .img_hash .PHash .create ()
120+ source = cv2 .resize (source , (hash_size , hash_size ), interpolation = cv2 .INTER_AREA )
121+ capture = cv2 .resize (capture , (hash_size , hash_size ), interpolation = cv2 .INTER_AREA )
122+ source_hash = phash .compute (source )
123+ capture_hash = phash .compute (capture )
124+ hash_diff = phash .compare (source_hash , capture_hash )
125+ return 1 - (hash_diff / 64.0 )
114126
115127
116128def compare_phash (source : MatLike , capture : MatLike , mask : MatLike | None = None ):
@@ -130,11 +142,7 @@ def compare_phash(source: MatLike, capture: MatLike, mask: MatLike | None = None
130142 source = cv2 .bitwise_and (source , source , mask = mask )
131143 capture = cv2 .bitwise_and (capture , capture , mask = mask )
132144
133- source_hash = __cv2_phash (source )
134- capture_hash = __cv2_phash (capture )
135- hash_diff = np .count_nonzero (source_hash != capture_hash )
136-
137- return 1 - (hash_diff / 64.0 )
145+ return __cv2_phash (source , capture )
138146
139147
140148def extract_and_compare_text (capture : MatLike , texts : Iterable [str ], methods_index : Iterable [int ]):
0 commit comments