Skip to content

DHash

Bases: BaseHasher

Implementation of the dHash (Difference Hashing) algorithm.

This class provides a specific strategy for image hashing. It calculates the hash by comparing the brightness (intensity) difference between adjacent pixels in a resized version of the image. It is very effective at identifying visual similarities while ignoring minor changes in color or compression.

Source code in tools/comparer/img_comparer/hasher/dhash.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class DHash(BaseHasher):
    """
    Implementation of the dHash (Difference Hashing) algorithm.

    This class provides a specific strategy for image hashing. It calculates
    the hash by comparing the brightness (intensity) difference between
    adjacent pixels in a resized version of the image. It is very effective
    at identifying visual similarities while ignoring minor changes in
    color or compression.
    """
    @staticmethod
    def compute_hash(image_path: Path, core_size: int) -> Union[np.ndarray, None]:
        """
        Calculates the dHash for a single image.

        The process includes:
        1. Loading the image in grayscale.
        2. Resizing it to (core_size + 1, core_size) to allow horizontal
           pixel comparison.
        3. Generating a boolean mask where each bit represents whether the
           left pixel is brighter than the right pixel.

        Args:
            image_path (Path): The file path to the image.
            core_size (int): The resolution used for resizing. The resulting
                hash length will be core_size squared (e.g., 8x8 = 64 bits).

        Returns:
            Union[np.ndarray, None]: A 1D NumPy array of boolean values
                representing the hash, or None if the image file is
                invalid or cannot be read.
        """
        image = cv2.imread(str(image_path), cv2.IMREAD_GRAYSCALE)

        if image is None:
            return None

        resized_image = cv2.resize(image, (core_size + 1, core_size), interpolation=cv2.INTER_AREA)
        gradient_difference = resized_image[:, 1:] > resized_image[:, :-1]

        return gradient_difference.flatten()

compute_hash(image_path, core_size) staticmethod

Calculates the dHash for a single image.

The process includes: 1. Loading the image in grayscale. 2. Resizing it to (core_size + 1, core_size) to allow horizontal pixel comparison. 3. Generating a boolean mask where each bit represents whether the left pixel is brighter than the right pixel.

Parameters:

Name Type Description Default
image_path Path

The file path to the image.

required
core_size int

The resolution used for resizing. The resulting hash length will be core_size squared (e.g., 8x8 = 64 bits).

required

Returns:

Type Description
Union[ndarray, None]

Union[np.ndarray, None]: A 1D NumPy array of boolean values representing the hash, or None if the image file is invalid or cannot be read.

Source code in tools/comparer/img_comparer/hasher/dhash.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@staticmethod
def compute_hash(image_path: Path, core_size: int) -> Union[np.ndarray, None]:
    """
    Calculates the dHash for a single image.

    The process includes:
    1. Loading the image in grayscale.
    2. Resizing it to (core_size + 1, core_size) to allow horizontal
       pixel comparison.
    3. Generating a boolean mask where each bit represents whether the
       left pixel is brighter than the right pixel.

    Args:
        image_path (Path): The file path to the image.
        core_size (int): The resolution used for resizing. The resulting
            hash length will be core_size squared (e.g., 8x8 = 64 bits).

    Returns:
        Union[np.ndarray, None]: A 1D NumPy array of boolean values
            representing the hash, or None if the image file is
            invalid or cannot be read.
    """
    image = cv2.imread(str(image_path), cv2.IMREAD_GRAYSCALE)

    if image is None:
        return None

    resized_image = cv2.resize(image, (core_size + 1, core_size), interpolation=cv2.INTER_AREA)
    gradient_difference = resized_image[:, 1:] > resized_image[:, :-1]

    return gradient_difference.flatten()