日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python使用imagehash庫生成ahash算法的示例代碼_python

作者:ponponon ? 更新時間: 2022-12-22 編程語言

知識點補充

aHash算法

Hash算法進行圖片相似度識別的本質,就是將圖片進行Hash轉化,生成一組二進制數字,然后通過比較不同圖片的Hash值距離找出相似圖片。aHash中文叫平均哈希算法,顧名思義,在進行轉化過程中將用到像素均值。

基本原理:

1、縮小尺寸。這樣做會去除圖片的細節,只保留結構、明暗等基本信息,目的是統一圖片大小,保證后續圖片都有相同長度的哈希值,方便距離計算。網上看到的案例基本都將尺寸縮小為8*8,64個像素點,暫時不清楚縮小為這個尺寸的原因,但如果覺得損失的信息太多,個人認為可以將尺寸適當調大,當然像素點多了后續計算就會稍慢一些。

2、灰度化處理。將圖片全部轉換為統一的灰度圖。

3、計算像素均值。計算像素的灰度平均值(此處均值出現)。

4、哈希值計算。將每個像素的灰度,與平均值進行比較。大于或等于平均值,記為1,小于平均值,記為0,由此生成二進制數組。

5、圖片配對,計算漢明距離。距離越近,越相似。當圖片縮小為8*8時,通常認為漢明距離小于10的一組圖片為相似圖片。

前言

有一個需求:計算圖片的相似度

需要解決兩個問題:

  • 生成 ahash
  • 存儲和計算 ahash 之間的距離

生成 ahash

『生成 ahash』 選用 python 下面的一個 imagehash 庫。(github:https://github.com/JohannesBuchner/imagehash)

from io import BytesIO
import numpy
import imagehash
from PIL import Image


def create_vector(file: BytesIO) -> bytes:
    image = Image.open(file)
    hash = imagehash.average_hash(image)

    _vector = []

    for h in hash.hash:
        _vector.extend(h)

    vector = bytes(
        numpy.packbits(
            [
                int(v)
                for v in _vector
            ],
            axis=-1
        ).tolist()
    )

    return vector

create_vector 函數輸出的類型是 bytes,就是二進制序列

imagehash.average_hash(image) 輸出的 hash 對象,hash 對象有一個 hash 屬性,這個屬性的類型是?list[list[bool]]打印出來就是長下面這樣子,其實就是一個 8x8=64 bit 的序列

[[False False False False False False False False]
?[ True False False False ?True False False False]
?[False False ?True ?True ?True ?True False False]
?[False False False ?True ?True False ?True ?True]
?[False False ?True ?True ?True False False False]
?[False ?True ?True ?True ?True False False False]
?[False ?True ?True ?True ?True False ?True ?True]
?[False False False ?True ?True False ?True ?True]]

向量數據庫

『存儲和計算 ahash 之間的距離』選用 milvus

創建集合

定義集合:

import settings
from pymilvus import (
    connections,
    Collection,
    FieldSchema,
    CollectionSchema,
    DataType,
)
from loggers import logger

connections.connect(
    host=settings.MILVUS_CONFIG.host,
    port=settings.MILVUS_CONFIG.port,
)

schema = CollectionSchema([
    FieldSchema("id", DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema("meta_id", DataType.INT64),
    FieldSchema("company_id", DataType.INT64),
    FieldSchema("image_vector", dtype=DataType.BINARY_VECTOR, dim=64)
])

# 集合不存在,則會自動創建集合;已存在,不會重復創建
collection = Collection(settings.MILVUS_CONFIG.collection.name, schema)

使用的向量類型是?dtype=DataType.BINARY_VECTOR,

為什么不選 float 是因為我不知道怎么把 ahash 轉成 float

插入 ahash 到 milvus

class TestVector(unittest.TestCase):
    def test_insert_vector(self):
        """
        插入 ahash 到 milvus
        python -m unittest testing.test_milvus.TestVector.test_insert_vector
        """

        oss_file_path = 'image_hash/testing/WechatIMG193.jpeg'

        file = BytesIO(bucket.get_object(oss_file_path).read())
        vector = create_vector(file)
        m_pk = insert_vector(vector, meta_id=2, company_id=1)
        logger.debug(f'milvus pk: {m_pk}')

查詢 ahash from milvus

def test_search(self):
    """
    批量調用后端接口入庫
    python -m unittest testing.test_milvus.TestVector.test_search
    """
    oss_file_path = 'image_hash/testing/WechatIMG193.jpeg'

    file = BytesIO(open(BASE_DIR/'testing'/'resource'/'WechatIMG193.jpeg','rb').read())
    vector = create_vector(file)

    logger.debug(vector)

    rows: list[dict[str, Any]] = collection.search(
        data=[vector],
        param={"metric_type": 'L2', "params": {"nprobe": 32}},
        anns_field='image_vector',
        output_fields=['id', 'meta_id', 'company_id'],
        limit=10,
    )
    logger.debug(rows)
    logger.debug(type(rows))

原文鏈接:https://segmentfault.com/a/1190000042869895

欄目分類
最近更新