【问题标题】:Remove Image Duplicates using Hashing in Python在 Python 中使用哈希删除图像重复项
【发布时间】:2022-06-24 15:52:52
【问题描述】:

我正在对一个图像数据集执行数据清理,其中存在人脸的重复图像。重复的图像可能并不完全相似,但它们几乎相同。

为了实现这一点,我使用average hashing 首先找到所有图像的哈希值,然后找到哈希值 w.r.t 的差异。目录中的所有图像。差异小于 15 的图像被认为是重复的,并且只有一个来自重复的图像应存在于清理后的数据集中。

下面是代码实现:
首先,我们计算所有图像的hash_values 并返回image_ids 和各自的hash_values

def calculate_hash(dir):
    """Generate Hash Values for all images in a directory

    Args:
        dir (str): Directory to search for images

    Returns:
        hash_values (list): List of hash values for all images in the directory
        image_ids (list): List of image ids for all images in the directory
    """

    hash_values = []
    image_ids = []

    for file in os.listdir(dir):

        path = os.path.join(dir, file)
        img = Image.open(path)

        hash = imagehash.average_hash(img)

        hash_values.append(hash)
        image_ids.append(file)

    return image_ids, hash_values

# Obtain image_ids and respective hash values
image_ids, hash_values = calculate_hash("D:/test_dir/images/test_duplicates")

然后我们准备一个数据框,其中包含image_idshash_values 以及所有 image_id 差异的附加列,并将其设置为 0。

def prepare_dataframe(image_ids, hash_values):

    # Create DataFrame with hash values and image ids
    df = pd.DataFrame(
        {
            "image_ids": image_ids, 
            "hash_values": hash_values, 
            }
    )

    # Create new columns in df with image_ids having hash difference value=0 
    for i in range(len(df.image_ids)):
        df[f"diff_{image_ids[i]}"] = 0

    return df

# Obtain dataframe
df = prepare_dataframe(image_ids, hash_values)

这就是准备好的数据框的样子。图像 1,2 完全不同。并且图像 3.1、3.2、3.3 是重复的(通过目视检查)。最终清理后的数据应该只包含图像 1,2,3.1。

现在我计算每个image_id w.r.t 每个image_id 的哈希值差异

def calculate_differences(df):

    # Obtain difference for every image_id one by one
    for i in range(len(df.hash_values)):
        differences = []

        for j in range(len(df.hash_values)):
            differences.append(df.hash_values[i] - df.hash_values[j])

        # Store the difference values for every image_id
        df.iloc[i, 2:] = differences

    return df

df = calculate_differences(df)

这为我们提供了以下数据框:

从哈希差值中可以清楚地看出 3.1、3.2 和 3.3 是重复的。但我不明白如何提取所需的输出,即unique_image_ids = [1,2,3.1]列表

我编写了以下代码,但它会删除任何具有重复的图像,即 3.1 也会从最终数据帧中删除。

# For every image_id, find the column values having value < 15 more than once and delete respective rows

def remove_duplicates(df):
    
        for i in range(len(df.image_ids)):
            clean_df = df.drop(df[df[f"diff_{df.image_ids[i]}"] < 15].index)
    
        return clean_df

clean_df = remove_duplicates(df)

所需的输出也应该有图像 3.1,但它没有出现在数据框中。

有没有优化的方法来实现这一点?

【问题讨论】:

    标签: python pandas dataframe image deep-learning


    【解决方案1】:

    使用以下数据框:

    import pandas as pd
    
    df = pd.DataFrame(
        {
            "image_ids": ["1.jpg", "2.jpg", "3.1.jpg", "3.2.jpg", "3.3.jpg", "3.4.jpg"],
            "hash_values": [
                "ff547aqu1f5",
                "ff197aqu1f5",
                "ff224aqu1f5",
                "ff349aqu1f5",
                "ff447aqu1f5",
                "ff999aqu1f5",
            ],
            "diff_1.jpg": [0, 33, 28, 28, 26, 28],
            "diff_2.jpg": [33, 0, 33, 31, 31, 31],
            "diff_3.1.jpg": [28, 33, 0, 8, 6, 8],
            "diff_3.2.jpg": [28, 31, 8, 0, 4, 2],
            "diff_3.3.jpg": [26, 31, 6, 4, 0, 2],
            "diff_3.4.jpg": [28, 31, 8, 2, 2, 0],
        }
    )
    

    你可以这样过滤:

    def remove_duplicates(df):
        mask = (df[df.columns[2:]] > 0) & (df[df.columns[2:]] < 15)
        return df[~(pd.DataFrame(mask).any(axis=1))].reset_index(drop=True)
    
    print(remove_duplicates(df))
    # Output
      image_ids  hash_values  diff_1.jpg  diff_2.jpg  diff_3.1.jpg  diff_3.2.jpg  diff_3.3.jpg  diff_3.4.jpg
    0     1.jpg  ff547aqu1f5           0          33            28            28            26            28
    1     2.jpg  ff197aqu1f5          33           0            33            31            31            31
    

    【讨论】:

      【解决方案2】:
      def remove_duplicates(df):
          # image = [range(0,6)]
          for i in range(len(df.image_ids)):
              # clean_df = df.
              clean_df = df.drop(df[df[f"diff_{df.image_ids[i]}"] < 15][1:].index)
      
          return clean_df
      
      clean_df = remove_duplicates(df)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 2015-04-25
        • 2013-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-03
        相关资源
        最近更新 更多