Vision Pipeline: Xây dựng hệ thống tìm kiếm hình ảnh sản phẩm (Visual Search) bằng CLIP model và LanceDB chỉ trong 15 phút

AI Hunter

Member
Thành viên BQT
Vision Pipeline: Xây dựng hệ thống tìm kiếm hình ảnh sản phẩm (Visual Search) bằng CLIP model và LanceDB chỉ trong 15 phút

Khách hàng của bạn nhìn thấy một chiếc áo đẹp trên Instagram, họ chụp màn hình lại và muốn tìm mua nó trên website của bạn. Nếu bạn chỉ có thanh tìm kiếm bằng chữ (Text Search), bạn đã mất vị khách đó.

Vision Pipeline Xây dựng hệ thống tìm kiếm hình ảnh sản phẩm (Visual Search) bằng CLIP model v...jpg

Năm 2026 là kỷ nguyên của **Multimodal AI** (Đa phương thức). Hôm nay, tôi sẽ hướng dẫn các bạn xây dựng một hệ thống **Visual Search** (Tìm kiếm bằng hình ảnh) hiệu suất cao.
Điểm đặc biệt:
  • Không cần Server riêng (Serverless).
  • Không cần Docker.
  • Code chạy trực tiếp trên Laptop với LanceDBCLIP.

1. Kiến trúc hệ thống​

Hệ thống hoạt động dựa trên nguyên lý Vector Embeddings:
1. CLIP Model: Biến bức ảnh (hoặc văn bản) thành một chuỗi số (Vector 512 chiều).
2. LanceDB: Lưu trữ và tìm kiếm các vector này với tốc độ siêu nhanh (gần như tức thời).



2. Chuẩn bị môi trường​

Chúng ta cần cài đặt thư viện để xử lý ảnh và database.

Bash:
pip install lancedb torch transformers pillow pandas

3. Triển khai Code (Python)​


Tạo file visual_search.py.

Bước 1: Khởi tạo CLIP Model (Bộ não)​

Chúng ta dùng model CLIP của OpenAI (thông qua Hugging Face) để "hiểu" hình ảnh.

Python:
import lancedb
import pandas as pd
from transformers import CLIPProcessor, CLIPModel
from PIL import Image
import torch
import os

# 1. Load Model CLIP
print("🧠 Đang tải CLIP Model...")
model_id = "openai/clip-vit-base-patch32"
model = CLIPModel.from_pretrained(model_id)
processor = CLIPProcessor.from_pretrained(model_id)

def get_image_embedding(image_path):
    """Chuyển đổi 1 file ảnh thành Vector"""
    image = Image.open(image_path)
    # Xử lý ảnh và đưa vào model
    inputs = processor(images=image, return_tensors="pt", padding=True)
    with torch.no_grad():
        outputs = model.get_image_features(**inputs)
    # Chuẩn hóa vector và chuyển về dạng list
    return outputs.detach().numpy()[0].tolist()

Bước 2: Xây dựng Database (LanceDB)​

LanceDB lưu dữ liệu trực tiếp vào ổ cứng (file system), cực kỳ tiện lợi.

Python:
# 2. Setup LanceDB
db = lancedb.connect("./my_product_db") # Tạo DB folder ngay tại đây

def ingest_data(image_folder):
    """Quét thư mục ảnh và lưu vào DB"""
    data = []
    print(f"📂 Đang quét ảnh từ: {image_folder}...")
   
    for filename in os.listdir(image_folder):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            path = os.path.join(image_folder, filename)
            try:
                # Tạo vector cho từng ảnh
                vector = get_image_embedding(path)
                data.append({
                    "filename": filename,
                    "vector": vector,
                    "path": path
                })
                print(f" -> Đã Index: {filename}")
            except Exception as e:
                print(f"Lỗi {filename}: {e}")
   
    # Tạo bảng 'products' (nếu có rồi thì ghi đè)
    if data:
        db.create_table("products", data=data, mode="overwrite")
        print(f"✅ Đã lưu {len(data)} sản phẩm vào LanceDB.")
    else:
        print("⚠️ Không tìm thấy ảnh nào.")

# Giả sử bạn có thư mục 'images' chứa ảnh sản phẩm
# ingest_data("./images")

Bước 3: Thực hiện tìm kiếm (Search)​

Bây giờ là lúc phép màu xảy ra. Bạn đưa vào một ảnh (query), hệ thống tìm ảnh tương đồng nhất.

Python:
def search_similar_product(query_image_path):
    print(f"\n🔍 Đang tìm sản phẩm giống với: {query_image_path}")
   
    # 1. Tạo vector cho ảnh query
    query_vector = get_image_embedding(query_image_path)
   
    # 2. Mở bảng và tìm kiếm vector gần nhất (Nearest Neighbor)
    tbl = db.open_table("products")
   
    # Tìm top 3 kết quả, trả về DataFrame pandas
    results = tbl.search(query_vector).limit(3).to_pandas()
   
    print("--- KẾT QUẢ TÌM KIẾM ---")
    for index, row in results.iterrows():
        # _distance càng thấp nghĩa là càng giống
        print(f"Top {index+1}: {row['filename']} (Độ sai lệch: {row['_distance']:.4f})")

# --- CHẠY THỬ ---
if __name__ == "__main__":
    # Uncomment dòng dưới để index dữ liệu lần đầu
    # ingest_data("./my_images")
   
    # Tìm kiếm
    search_similar_product("./test_input.jpg")

4. Tại sao lại dùng LanceDB?​

  • Tốc độ: LanceDB được viết bằng Rust, tối ưu hóa cho việc truy xuất vector trên đĩa cứng. Nó nhanh hơn việc bạn dùng thư viện `faiss` thuần túy khi dữ liệu lớn.
  • Đơn giản: Không cần cài đặt server. `pip install` là chạy.
  • Scalability: Tuy là embedded nhưng nó có thể lưu trữ hàng tỷ vector mà không "ăn" hết RAM của bạn (vì nó lưu trên ổ cứng).

5. Mở rộng: Tìm ảnh bằng văn bản (Text-to-Image)​

Vì CLIP là model đa phương thức, bạn hoàn toàn có thể tìm ảnh bằng chữ!
Chỉ cần thay hàm `get_image_embedding` bằng `get_text_embedding` (dùng `model.get_text_features`), bạn có thể gõ: "Chiếc váy màu đỏ chấm bi" và hệ thống sẽ trả về đúng bức ảnh đó.

Kết luận​

Chỉ với 70 dòng code Python, bạn đã sở hữu công nghệ lõi của Pinterest hay Google Lens. Hãy tích hợp nó vào dự án thương mại điện tử của bạn ngay hôm nay!
 
Back
Top