5
5
import Levenshtein
6
6
import numpy as np
7
7
from cv2 .typing import MatLike
8
- from scipy import fft
9
8
10
9
from utils import (
11
10
BGRA_CHANNEL_COUNT ,
@@ -90,27 +89,40 @@ def compare_template(source: MatLike, capture: MatLike, mask: MatLike | None = N
90
89
return 1 - (min_val / max_error )
91
90
92
91
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 )
114
126
115
127
116
128
def 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
130
142
source = cv2 .bitwise_and (source , source , mask = mask )
131
143
capture = cv2 .bitwise_and (capture , capture , mask = mask )
132
144
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 )
138
146
139
147
140
148
def extract_and_compare_text (capture : MatLike , texts : Iterable [str ], methods_index : Iterable [int ]):
0 commit comments