Skip to content

Commit 10c68e1

Browse files
committed
Add floating point version of hash.
1 parent c33e262 commit 10c68e1

4 files changed

Lines changed: 43 additions & 3 deletions

File tree

.dockerignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
.venv
22
ThreatExchange
3-
!ThreatExchange/hashing/pdq
3+
!ThreatExchange/hashing/pdq/cpp
44
tests

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pdqhash-python
1+
# pdqhash-python [![CircleCI](https://circleci.com/gh/faustomorales/pdqhash-python.svg?style=svg)](https://circleci.com/gh/faustomorales/pdqhash-python)
22
These are Python bindings to the PDQ perceptual hash released by Facebook. Note that the bindings are provided under the MIT license but the PDQ source code is licensed separately under its own license (see the `ThreatExchange/hashing/pdq` folder).
33

44
## Installation
@@ -27,6 +27,9 @@ hash_vector, quality = pdqhash.compute(image)
2727
# - Rotated 90 degrees and flipped vertically
2828
# - Rotated 90 degrees and flipped horizontally
2929
hash_vectors, quality = pdqhash.compute_dihedral(image)
30+
31+
# Get the floating point values of the hash.
32+
hash_vector_float, quality = pdqhash.compute_float(image)
3033
```
3134

3235
## Contributing

pdqhash/bindings.pyx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ cdef extern from "../ThreatExchange/hashing/pdq/cpp/hashing/pdqhashing.cpp" name
2121
int& quality
2222
)
2323

24+
cdef extern from "../ThreatExchange/hashing/pdq/cpp/hashing/pdqhashing.cpp" namespace "facebook::pdq::hashing":
25+
void pdqFloat256FromFloatLuma(
26+
float* fullBuffer1,
27+
float* fullBuffer2,
28+
int numRows,
29+
int numCols,
30+
float buffer64x64[64][64],
31+
float buffer16x64[16][64],
32+
float output_buffer16x16[16][16],
33+
int& quality
34+
)
35+
2436
cdef extern from "../ThreatExchange/hashing/pdq/cpp/hashing/pdqhashing.cpp" namespace "facebook::pdq::hashing":
2537
void pdqDihedralHash256esFromFloatLuma(
2638
float* fullBuffer1,
@@ -77,6 +89,28 @@ def compute(np.ndarray[char, ndim=3] image):
7789

7890
return hash_to_vector(hash_value.w), quality
7991

92+
def compute_float(np.ndarray[char, ndim=3] image):
93+
cdef np.ndarray[float, ndim=2] gray = (image[:, :, 0]*0.299 + image[:, :, 1]*0.587 + image[:, :, 2] * 0.114).astype('float32')
94+
cdef np.ndarray[float, ndim=2] placeholder = np.zeros_like(gray)
95+
cdef int quality
96+
cdef int numRows = gray.shape[0]
97+
cdef int numCols = gray.shape[1]
98+
cdef float buffer64x64[64][64]
99+
cdef float buffer16x64[16][64]
100+
cdef float buffer16x16[16][16]
101+
cdef float* fullBuffer1 = &gray[0, 0]
102+
cdef float* fullBuffer2 = &placeholder[0, 0]
103+
pdqFloat256FromFloatLuma(
104+
fullBuffer1,
105+
fullBuffer2,
106+
numRows,
107+
numCols,
108+
buffer64x64,
109+
buffer16x64,
110+
buffer16x16,
111+
quality)
112+
return np.array(buffer16x16)[:, ::-1].flatten(), quality
113+
80114
def compute_dihedral(np.ndarray[char, ndim=3] image):
81115
cdef np.ndarray[float, ndim=2] gray = (image[:, :, 0]*0.299 + image[:, :, 1]*0.587 + image[:, :, 2] * 0.114).astype('float32')
82116
cdef np.ndarray[float, ndim=2] placeholder = np.zeros_like(gray)

tests/test_compute.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,10 @@ def test_basic(expected, image_name, threshold):
153153
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
154154
actual, quality = bindings.compute(image)
155155
assert (actual != expected).sum() <= threshold
156-
assert quality == 100
156+
157+
actual_float, quality = bindings.compute_float(image)
158+
actual_float = actual_float > np.median(actual_float)
159+
assert (actual_float != expected).sum() <= threshold
157160

158161
transforms = dict(
159162
r0=image,

0 commit comments

Comments
 (0)