@@ -40,20 +40,20 @@ class Kernel(ABC):
4040 """
4141
4242 def __init__ (self , plugin ):
43- # Containment of the plugin allows the kernel to cherry-pick required state
43+ # Containment of the plugin allows the kernel to cherry-pick required state.
4444 self ._plugin = plugin
4545
4646 @abstractmethod
47- def equivalent_hash (self , actual , expected , marker = None ):
47+ def equivalent_hash (self , result , baseline , marker = None ):
4848 """
49- Determine whether the kernel considers the provided actual and
50- expected hashes as similar.
49+ Determine whether the kernel considers the provided result (actual)
50+ and baseline ( expected) hashes as similar.
5151
5252 Parameters
5353 ----------
54- actual : str
55- The hash of the test image.
56- expected : str
54+ result : str
55+ The hash of the image generated by the test .
56+ baseline : str
5757 The hash of the baseline image.
5858 marker : pytest.Mark
5959 The test marker, which may contain kwarg options to be
@@ -62,7 +62,7 @@ def equivalent_hash(self, actual, expected, marker=None):
6262 Returns
6363 -------
6464 bool
65- Whether the actual and expected hashes are deemed similar.
65+ Whether the result and baseline hashes are deemed similar.
6666
6767 """
6868
@@ -112,17 +112,16 @@ def update_summary(self, summary):
112112
113113 Returns
114114 -------
115- dict
116- The updated image comparison summary.
115+ None
117116
118117 """
119- return summary
118+ summary [ "kernel" ] = self . name
120119
121120
122121class KernelPHash (Kernel ):
123122 """
124123 Kernel that calculates a perceptual hash of an image for the
125- specified hash size (N).
124+ specified hash size (N) and high frequency factor .
126125
127126 Where the resultant perceptual hash will be composed of N**2 bits.
128127
@@ -132,31 +131,37 @@ class KernelPHash(Kernel):
132131
133132 def __init__ (self , plugin ):
134133 super ().__init__ (plugin )
135- # keep state of equivalence result
134+ # Keep state of the equivalence result.
136135 self .equivalent = None
137- # keep state of hash hamming distance (whole number) result
136+ # Keep state of hash hamming distance (whole number) result.
138137 self .hamming_distance = None
139- # value may be overridden by py.test marker kwarg
138+ # Value may be overridden by py.test marker kwarg.
140139 self .hamming_tolerance = (
141140 self ._plugin .hamming_tolerance or DEFAULT_HAMMING_TOLERANCE
142141 )
143- # the hash-size (N) defines the resultant N**2 bits hash size
142+ # The hash-size (N) defines the resultant N**2 bits hash size.
144143 self .hash_size = self ._plugin .hash_size
145- # the level of image detail or structure represented by perceptual hash
144+ # The level of image detail (high freq) or structure (low freq)
145+ # represented in perceptual hash thru discrete cosine transform.
146146 self .high_freq_factor = (
147147 self ._plugin .high_freq_factor or DEFAULT_HIGH_FREQUENCY_FACTOR
148148 )
149- # py.test marker kwarg
149+ # py.test marker kwarg.
150150 self .option = "hamming_tolerance"
151151
152- def equivalent_hash (self , actual , expected , marker = None ):
152+ def equivalent_hash (self , result , baseline , marker = None ):
153153 if marker :
154154 value = marker .kwargs .get (self .option )
155155 if value is not None :
156+ # Override with the decorator marker value.
156157 self .hamming_tolerance = int (value )
157- actual = imagehash .hex_to_hash (actual )
158- expected = imagehash .hex_to_hash (expected )
159- self .hamming_distance = actual - expected
158+ # Convert string hexdigest hashes to imagehash.ImageHash instances.
159+ result = imagehash .hex_to_hash (result )
160+ baseline = imagehash .hex_to_hash (baseline )
161+ # Unlike cryptographic hashes, perceptual hashes can measure the
162+ # degree of "similarity" through hamming distance bit differences
163+ # between the hashes.
164+ self .hamming_distance = result - baseline
160165 self .equivalent = self .hamming_distance <= self .hamming_tolerance
161166 return self .equivalent
162167
@@ -170,6 +175,7 @@ def generate_hash(self, buffer):
170175
171176 def update_status (self , message ):
172177 result = str () if message is None else str (message )
178+ # Only update the status message for non-equivalent hash comparisons.
173179 if self .equivalent is False :
174180 msg = (
175181 f"Hash hamming distance of { self .hamming_distance } bits > "
@@ -179,9 +185,9 @@ def update_status(self, message):
179185 return result
180186
181187 def update_summary (self , summary ):
188+ super ().update_summary (summary )
182189 summary ["hamming_distance" ] = self .hamming_distance
183190 summary ["hamming_tolerance" ] = self .hamming_tolerance
184- return summary
185191
186192
187193class KernelSHA256 (Kernel ):
@@ -192,8 +198,13 @@ class KernelSHA256(Kernel):
192198
193199 name = KERNEL_SHA256
194200
195- def equivalent_hash (self , actual , expected , marker = None ):
196- return actual == expected
201+ def equivalent_hash (self , result , baseline , marker = None ):
202+ # Simple cryptographic hash binary comparison. Interpretation of
203+ # the comparison result is that the hashes are either identical or
204+ # not identical. For non-identical hashes, it is not possible to
205+ # determine a heuristic of hash "similarity" due to the nature of
206+ # cryptographic hashes.
207+ return result == baseline
197208
198209 def generate_hash (self , buffer ):
199210 buffer .seek (0 )
0 commit comments