Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

README — Vietnam Celebrity Image Collection Pipeline

Source of Truth cho công cụ semi-automatic hỗ trợ thu thập dữ liệu hình ảnh người nổi tiếng Việt Nam: tự động tìm kiếm, lọc kỹ thuật, chấm điểm, gom shortlist — người vận hành chỉ cần review và chốt final.


Mục lục

  1. Tổng quan & Mục tiêu
  2. Yêu cầu kỹ thuật ảnh (Hard Requirements)
  3. Quickstart — Cài đặt & Chạy lần đầu
  4. Nguyên tắc thiết kế
  5. Kiến trúc tổng thể
  6. Workflow chuẩn (6 Phase)
  7. Danh sách Module
  8. Data Model & Candidate Lifecycle
  9. Cấu trúc thư mục
  10. Scoring & Threshold Strategy
  11. Chiến lược batch 100 người
  12. Stop Rules
  13. Manual Review Policy
  14. Logging & Observability
  15. Ước tính chi phí & Performance
  16. Công nghệ & Vision Models
  17. Thứ tự Implement
  18. Rủi ro & Mitigation
  19. Definition of Done
  20. Lưu ý Pháp lý & Đạo đức
  21. Phụ lục — CLI Reference
  22. Phụ lục — Candidate States
  23. Phụ lục — Config mẫu

1. Tổng quan & Mục tiêu

1.1 Bài toán

Thu thập 20–50 ảnh usable / người cho danh sách 14–100+ người nổi tiếng Việt Nam (KOLs, ca sĩ, diễn viên, vận động viên, YouTubers...).

Nếu làm thủ công hoàn toàn, bottleneck thực sự không phải khâu tìm ra kết quả, mà là:

  • Mở nhiều tab, lọc ảnh lỗi / bé / mờ bằng mắt thường
  • Lướt qua hàng loạt ảnh trùng cùng buổi chụp / outfit
  • Tải nhầm ảnh không usable
  • Quản lý metadata bị thiếu hoặc lệch

1.2 Mục tiêu công cụ

Công cụ không chịu trách nhiệm quyết định ảnh nào vào dataset. Công cụ chịu trách nhiệm các bước lặp lại và có thể tự động hóa:

Bước tự động hóa Ghi chú
Search ảnh theo từ khóa Đa dạng query template
Thu thập link / thumbnail / metadata Không tải gốc vội
Lọc sơ bộ theo tiêu chuẩn kỹ thuật Rẻ, nhanh trước
Ước lượng full-body Heuristic, không cần nhận diện danh tính
Loại ảnh trùng / gần trùng pHash + clustering
Chấm điểm & gom shortlist Ưu tiên ảnh đáng review trước

Manual review vẫn là bước kiểm soát cuối cùng để:

  • Xác nhận đúng người
  • Loại ảnh xấu / ngữ cảnh không phù hợp
  • Tránh ảnh quá giống nhau, cùng outfit / photoshoot
  • Quyết định danh sách final

1.3 Success Criteria

Chỉ số Mục tiêu
Scale 100 người / batch
Raw candidates / người 60–120 ảnh
Shortlist sau auto-filter 20–40 ảnh
Final usable / người 25–30 ảnh
Pipeline Có log, metadata, resume được

1.4 Non-goals (v1)

  • Xác minh danh tính 100% bằng face recognition
  • Auto-final selection không cần người review
  • Nhận diện cùng outfit / photoshoot hoàn hảo
  • Crawling không giới hạn mọi nguồn

2. Yêu cầu kỹ thuật ảnh (Hard Requirements)

Đây là các gate cứng — không đạt thì tự động loại, không cần xem tay:

Tiêu chí Yêu cầu
Độ phân giải min(width, height) > 400 px
Định dạng file .jpg, .jpeg, .png
Tỷ lệ khung hình Không cắt / crop phá khung gốc
Độ sắc nét Laplacian variance > ngưỡng cấu hình (mặc định: 80)
Đối tượng Người nổi tiếng Việt Nam
Bối cảnh Chấp nhận mọi ngữ cảnh phù hợp (sự kiện, biểu diễn, thể thao, đi biển...)
Số lượng / người Tối thiểu 20 — Tối đa 50 — Mục tiêu vận hành: 25–30

3. Quickstart — Cài đặt & Chạy lần đầu

3.1 Yêu cầu môi trường

Python >= 3.10
OS: macOS / Linux (Windows cần WSL2)
RAM: >= 8 GB (16 GB khuyến nghị nếu chạy batch lớn)
Disk: >= 20 GB free cho raw images

3.2 Cài đặt

git clone https://github.com/Purin1410/AIO_Datasets_Tool4ReIDProject.git
cd AIO_Datasets_Tool4ReIDProject

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

pip install -r requirements.txt

3.3 Cấu hình secrets

Không bao giờ để API key trong config.yaml hay commit lên Git.

cp .env.example .env
# Mở .env và điền:
#   SERPAPI_KEY=your_key_here
#   GOOGLE_CSE_KEY=your_key_here      # nếu dùng Google CSE
#   GOOGLE_CSE_CX=your_cx_id_here

File .env.example:

SERPAPI_KEY=
GOOGLE_CSE_KEY=
GOOGLE_CSE_CX=

3.4 Cài MediaPipe (Vision)

pip install mediapipe
# Hoặc nếu dùng YOLO:
pip install ultralytics

3.5 Chạy lần đầu với roster mẫu

# 1. Tạo roster
cp data/roster/roster_example.csv data/roster/roster.csv
# Chỉnh sửa roster.csv theo danh sách nhân vật của bạn

# 2. Validate roster
python -m src.main validate-roster --roster data/roster/roster.csv

# 3. Harvest candidates (chạy search, CHƯA download ảnh gốc)
python -m src.main harvest --roster data/roster/roster.csv

# 4. Fast filter (thumbnail + full-body check)
python -m src.main fast-filter --batch all

# 5. Download ảnh gốc (chỉ ảnh pass sơ bộ)
python -m src.main download --only shortlisted

# 6. Strict filter (resolution, blur, dedupe)
python -m src.main strict-filter --batch all

# 7. Build review queue
python -m src.main build-review-queue --batch all

# 8. Mở UI review
streamlit run src/ui/streamlit_app.py

# 9. Export kết quả
python -m src.main export --status accepted

4. Nguyên tắc thiết kế

# Nguyên tắc Lý do
1 Link-first, download-later Tránh tốn băng thông và disk cho ảnh rác
2 Cascade filtering Filter rẻ trước, filter nặng sau; không chạy model nặng toàn bộ
3 Semi-automatic, not fully automatic Tool tăng tốc — người vận hành vẫn là quyết định cuối
4 Review throughput > search throughput Tăng tốc lớn nhất đến từ giảm số ảnh phải xem tay
5 Resumable & auditable Mọi bước có log, metadata, trạng thái; có thể dừng giữa chừng và chạy tiếp
6 Backend-agnostic Search connector phải có abstraction layer; dễ thay Google / SerpAPI
7 Config-driven, not hardcoded Mọi threshold đều ở config.yaml; không hardcode trong code
8 Secrets in .env, never in config Bảo mật API key

5. Kiến trúc tổng thể

[Input Roster (.csv/.xlsx)]
    │
    ▼
[roster_manager]           — validate, chuẩn hóa ID, tracking status
    │
    ▼
[query_builder]            — sinh bộ queries đa dạng / nhân vật
    │
    ▼
[search_connector]         — gọi API (SerpAPI / Google CSE / ...)
    │
    ▼
[result_store]             — lưu raw results (SQLite / JSONL)
    │
    ▼
[url_prefilter]            — loại URL rác, domain blacklist, trùng sau normalize
    │
    ▼
[thumbnail_fetcher]        — tải thumbnail nhỏ (timeout ngắn)
    │
    ▼
[fast_visual_filter]       — person detection, full-body heuristic, poster rejection
    │
    ▼
[candidate_scorer]         — tổng hợp score đa chiều
    │
    ▼
[download_manager]         — tải ảnh gốc (chỉ ảnh pass sơ bộ)
    │
    ▼
[strict_technical_filter]  — format, min-side > 400, blur check
    │
    ▼
[dedupe_engine]            — exact + near-duplicate (pHash)
    │
    ▼
[diversity_manager]        — cân bằng góc chụp / bối cảnh
    │
    ▼
[review_queue_builder]     — tạo shortlist tối ưu per person
    │
    ▼
[manual_review_ui]         — grid view + phím nóng
    │
    ▼
[exporter]                 — export accepted images + metadata + audit log

6. Workflow chuẩn (6 Phase)

Phase A — Chuẩn bị Roster

  1. Tạo / cập nhật roster.csv với các cột: person_id, person_name, field, aliases, target_final_count
  2. Chạy validate-roster để phát hiện ID trùng, thiếu cột
  3. Kiểm tra status từng người: todo / in_progress / done / blocked

Checkpoint: Roster hợp lệ, không có ID trùng → pass Phase A.


Phase B — Harvest Candidates

  1. query_builder sinh 4–8 query / người (base + full-body bias + field-specific)
  2. search_connector gọi API lấy kết quả (mặc định 30 kết quả / query)
  3. result_store lưu raw results vào SQLite
  4. Chưa tải ảnh gốc

Checkpoint: raw_results count / người đạt ≥ 60 → pass Phase B.


Phase C — Fast Filter

  1. url_prefilter chuẩn hóa URL, loại domain blacklist, loại trùng
  2. thumbnail_fetcher tải thumbnail nhỏ (timeout 5s, retry 2 lần)
  3. fast_visual_filter chạy person detection + full-body heuristic
  4. candidate_scorer chấm điểm tổng hợp
  5. Chỉ candidates score đạt ngưỡng mới vào download queue

Checkpoint: shortlisted_count / người ≥ 30 → pass Phase C.


Phase D — Download & Strict Filter

  1. download_manager tải ảnh gốc (concurrent, retry 3 lần, checksum)
  2. strict_technical_filter kiểm tra format, resolution, blur
  3. dedupe_engine loại exact duplicate (file hash) và near-duplicate (pHash)
  4. diversity_manager gắn bucket đa dạng (góc chụp, bối cảnh, orientation)

Checkpoint: technical_pass count / người ≥ 25 → pass Phase D.


Phase E — Manual Review

  1. review_queue_builder tạo shortlist tối ưu (top N theo score, 1–3 ảnh / cluster)
  2. Reviewer mở Streamlit UI, review từng ảnh với phím nóng A / R / S / U
  3. Gắn nhãn: accepted, rejected_*, saved_raw, unsure
  4. Nếu sau review chưa đủ target_final_count, chạy fill-gap: bổ sung query mới

Phase F — Export & Sync

  1. exporter xuất ảnh final vào thư mục export chuẩn hóa theo person_id
  2. Xuất final_metadata.csvreview_log.csv
  3. Sync lên Google Drive / hệ thống quản lý chung
  4. Cập nhật status trong roster → done hoặc blocked

7. Danh sách Module

7.1 roster_manager

Chức năng: Đọc, validate và tracking danh sách nhân vật.

Input: roster.csv hoặc roster.xlsx

Schema chuẩn:

person_id,person_name,field,aliases,target_final_count,status,notes
VNC001,Son Tung M-TP,singer,"Son Tung|Nguyen Thanh Tung",30,todo,
VNC002,H'Hen Nie,model,"HHen Nie|H Hen Nie",30,todo,
VNC003,Quang Hai,athlete,"Nguyen Quang Hai",25,done,Đã đủ ảnh

Trách nhiệm:

  • Validate schema và kiểu dữ liệu
  • Loại / cảnh báo ID trùng
  • Đánh dấu người đã đủ ảnh / đang làm / chưa làm / bị block
  • Hỗ trợ --person flag để chạy riêng 1 người
  • Hỗ trợ --batch flag để chạy theo nhóm field

7.2 query_builder

Chức năng: Sinh bộ query search đa dạng cho từng nhân vật.

Input: person_name, aliases, field

Output: Danh sách query strings

Template chuẩn:

Nhóm Query
Base {name}, {name} vietnam, {name} official, {name} instagram
Full-body bias {name} full body, {name} standing, {name} event, {name} red carpet
Singer / Performer {name} concert, {name} performance, {name} stage
Actor / Actress {name} premiere, {name} press event, {name} photoshoot
Athlete {name} competition, {name} training, {name} sport event
Model / KOL {name} lookbook, {name} editorial, {name} fashion week

Lưu ý:

  • Sinh query từ aliases để tránh bỏ sót ảnh dùng tên khác
  • Cho phép override thủ công trong roster.csv cột custom_queries
  • Không query quá rộng gây nhiễu (e.g. tên quá ngắn mà không kèm vietnam)

7.3 search_connector

Chức năng: Giao tiếp với backend image search, chuẩn hóa output.

Interface bắt buộc:

class ImageSearchProvider:
    def search_images(self, query: str, limit: int) -> list[dict]:
        """
        Trả về list dict theo schema chuẩn nội bộ.
        KHÔNG expose raw payload của provider ra ngoài module này.
        """
        ...

Schema output chuẩn hóa (nội bộ):

{
  "query": "Son Tung M-TP full body",
  "rank": 1,
  "title": "...",
  "source_page": "https://...",
  "image_url": "https://...",
  "thumbnail_url": "https://...",
  "width_hint": 1200,
  "height_hint": 1800,
  "provider": "serpapi",
  "fetched_at": "2024-01-01T10:00:00Z"
}

Providers hỗ trợ:

  • SerpApiProvider — Google Images qua SerpAPI (ổn định, có cost)
  • GoogleCSEProvider — Google Custom Search JSON API (free tier giới hạn)
  • Dễ mở rộng thêm provider mới

Trách nhiệm:

  • Retry + exponential backoff khi lỗi 429 / 5xx
  • Rate limit handling (xem Section 15)
  • Cache raw response để tránh gọi lại API khi re-run
  • Log số query đã dùng / ngày

7.4 result_store

Chức năng: Lưu trữ toàn bộ raw results và intermediate state.

Backend: SQLite (mặc định) — đủ cho scale 100 người, không cần setup server.

Bảng chính:

Bảng Mô tả
persons Danh sách nhân vật + status
queries Mỗi query đã chạy per person
raw_results Kết quả thô từ search API
candidates Kết quả sau prefilter, kèm state machine
technical_metrics Kết quả strict filter per candidate
visual_metrics Kết quả fast visual filter per candidate
review_records Log review action của reviewer
exports Lịch sử export

Mục tiêu: Có thể dừng pipeline giữa chừng và resume mà không mất trạng thái.


7.5 url_prefilter

Chức năng: Loại URL rác trước khi tải bất kỳ thứ gì.

Rules:

  • Chỉ giữ URL có extension / content-type là jpg, jpeg, png
  • Loại URL từ domain blacklist (thumbnail host chất lượng thấp, watermark nặng)
  • Loại URL thumbnail cực nhỏ (suy ra từ URL params nếu có)
  • Normalize URL trước khi dedupe (strip query params tracking)
  • Loại URL duplicate sau normalize

Output: Danh sách URL hợp lệ để fetch thumbnail.


7.6 thumbnail_fetcher

Chức năng: Tải thumbnail nhỏ để chạy fast visual filter mà không tốn bandwidth tải ảnh gốc.

Yêu cầu:

  • Timeout: 5 giây (không đợi lâu hơn)
  • Retry: tối đa 2 lần
  • Cache local theo hash URL (tránh fetch lại khi re-run)
  • Resize về max 480px trước khi lưu để tiết kiệm disk

Output: local_thumbnail_path, detected_width, detected_height, mime_type


7.7 fast_visual_filter

Chức năng: Chạy các kiểm tra thị giác nhanh trên thumbnail.

Sub-checks:

a. person_presence_check

  • Có người trong ảnh không?
  • Số lượng person bounding boxes
  • Subject chính là person box lớn nhất

b. full_body_check (core gate)

Heuristic full-body — không cần nhận diện đúng người:

Điều kiện Ngưỡng khuyến nghị
Person bbox height / image height ≥ 55–70%
Đầu không bị cắt mất Kiểm tra y_top của bbox
Chân không bị cắt quá nặng Kiểm tra y_bottom của bbox
Pose: thấy shoulder + hip + knee MediaPipe Pose landmarks
Pose: thấy ankle (nếu có) Bonus score

c. composition_check (optional)

  • Ảnh có quá nhiều text / poster / collage không?
  • Subject có quá nhỏ so với khung (< 20% diện tích) không?

Output:

{
  "has_person": bool,
  "person_count": int,
  "main_bbox_ratio": float,       # height of main bbox / image height
  "full_body_score": float,       # 0.0 - 1.0
  "composition_score": float,     # 0.0 - 1.0
  "fast_pass": bool
}

7.8 candidate_scorer

Chức năng: Tổng hợp điểm từ nhiều tín hiệu để xếp hạng candidates.

Công thức:

candidate_score =
    0.35 × full_body_score
  + 0.20 × subject_prominence_score
  + 0.15 × resolution_hint_score
  + 0.15 × source_quality_score
  + 0.10 × composition_score
  + 0.05 × query_diversity_score

Trọng số có thể điều chỉnh trong config.yaml mục scoring.weights.

Phân tier:

Tier Điều kiện Hành động
A score cao, full-body tốt Download ngay, review trước
B đủ điều kiện sơ bộ nhưng chưa mạnh Giữ lại xem sau
C không người / quá nhỏ / poster rõ ràng Auto-reject

7.9 download_manager

Chức năng: Tải ảnh gốc cho candidates đã pass sơ bộ.

Yêu cầu:

  • Concurrent download (mặc định: 4 workers, cấu hình được)
  • Timeout: 20 giây / ảnh
  • Retry: 3 lần với exponential backoff
  • Checksum SHA256 sau download
  • Không tải lại file đã có (kiểm tra checksum hoặc path)
  • Ghi log lỗi HTTP status + URL cho ảnh fail

Output: local_image_path, file_size_bytes, sha256_checksum, http_status


7.10 strict_technical_filter

Chức năng: Kiểm tra các yêu cầu kỹ thuật "cứng" trên ảnh gốc đã download.

Hard gates (bắt buộc):

Check Điều kiện pass
Format File header là JPEG hoặc PNG (không tin vào extension)
Resolution min(width, height) > 400
Corrupted Đọc được bằng Pillow / OpenCV không lỗi
Blur Laplacian variance > blur_threshold (mặc định: 80)

Soft checks (optional, ghi vào metadata):

  • Watermark detection (heuristic)
  • Text-heavy detection
  • NSFW flag nếu cần

Output: format_ok, resolution_ok, blur_score, technical_pass


7.11 dedupe_engine

Chức năng: Loại ảnh trùng và gần trùng.

Lý do bắt buộc: Nếu không có bước này, reviewer sẽ mất thời gian vào hàng loạt ảnh cùng buổi chụp / outfit / pose.

3 mức dedupe:

Level Phương pháp Mục tiêu
1 — Exact SHA256 file hash Cùng file y hệt
2 — Near-duplicate pHash / dHash, Hamming distance ≤ 8 Ảnh resize, crop nhẹ, nén khác nhau
3 — Semantic (v2) Image embeddings + cosine similarity clustering Cùng buổi chụp, outfit

Output: duplicate_group_id, is_primary_representative, duplicate_level


7.12 diversity_manager

Chức năng: Cân bằng shortlist để không dồn quá nhiều ảnh cùng một kiểu.

Bucket phân loại:

Dimension Buckets
Orientation portrait / landscape / square
Setting indoor / outdoor / stage / sports / beach
Framing close-up / half-body / full-body
Facing left / right / front / back
Source instagram / news / event / fan_page
Query family base / full-body-bias / field-specific

Output: diversity_bucket, cluster_rank (rank trong bucket, 1 = đại diện tốt nhất)


7.13 review_queue_builder

Chức năng: Tạo shortlist review tối ưu cho từng người.

Quy tắc:

  • Lấy top N ảnh theo score sau khi dedupe
  • Mỗi cluster chỉ lấy 1–3 ảnh đại diện
  • Ưu tiên phủ đủ các diversity bucket
  • Sắp xếp: Tier A trước, trong Tier A sort by score giảm dần

Stop rule khi build queue:

  • Dừng thêm nếu đã có 25 ảnh Tier A + 15 ảnh Tier B, hoặc
  • Đã có ≥ 35 provisional pass bất kể tier

Output: Ordered list of candidate_id chờ reviewer xem.


7.14 manual_review_ui

Chức năng: Giao diện review nhanh với phím nóng, chạy bằng Streamlit.

Layout:

  • Grid view (4–6 ảnh / hàng)
  • Click vào ảnh → preview full size + metadata (score, source, query, resolution)

Phím nóng:

Phím Hành động
A Accept
R Reject (hỏi lý do)
S Save raw link only (chưa chắc dùng)
U Unsure (để lại xem sau)
O Mở source page trong browser
D Download original nếu chưa có

Bộ lọc sidebar:

  • Chỉ xem: technical pass / full-body pass / unique / unresolved
  • Sort by: score / source / query / resolution

Nhãn reject:

  • rejected_wrong_person
  • rejected_low_quality
  • rejected_not_full_body
  • rejected_duplicate_vibe
  • rejected_bad_crop
  • rejected_bad_context

7.15 exporter

Chức năng: Xuất dữ liệu final để đưa vào Drive / metadata chung.

Output files:

File Mô tả
accepted_images/{person_id}/ Thư mục ảnh final, đặt tên {person_id}_{seq:04d}.jpg
final_metadata.csv Metadata đầy đủ mỗi ảnh accepted
review_log.csv Toàn bộ action của reviewer
raw_candidates.csv Toàn bộ candidates kèm state cuối
audit_summary.txt Tóm tắt số liệu mỗi người

Schema final_metadata.csv:

person_id,person_name,field,image_id,local_path,source_page,image_url,width,height,format,candidate_score,final_status,reviewer,reviewed_at,notes

7.16 audit_logger

Chức năng: Ghi lại mọi quyết định và lỗi quan trọng.

Log nên ghi:

  • Query nào sinh ra candidate nào
  • Candidate bị reject ở bước nào và lý do
  • Ảnh nào được accept/reject bởi reviewer nào, lúc nào
  • Download error + URL
  • API quota consumed per day

Format: Structured JSON logs + human-readable summary per person.


7.17 config_manager

Chức năng: Quản lý toàn bộ config hệ thống từ config.yaml.

Nguyên tắc:

  • API keys không được trong config.yaml — phải từ .env
  • Mọi threshold đều configurable, không hardcode
  • Hỗ trợ --config flag để chỉ định file config khác

Xem Phụ lục 23 để biết full config example.


8. Data Model & Candidate Lifecycle

8.1 Candidate State Machine

new
 └─► url_prefilter_rejected
 └─► thumbnail_fetching
      └─► thumbnail_failed
      └─► thumbnail_ready
           └─► fast_filter_rejected
           └─► fast_filter_passed
                └─► download_queued
                     └─► download_failed
                     └─► downloaded
                          └─► technical_rejected
                          └─► deduped_out
                          └─► shortlisted
                               └─► accepted
                               └─► rejected
                               └─► saved_raw
                               └─► unsure

Quy ước: Tất cả state dùng lowercase_snake_case. Không dùng UPPERCASE trong code hay database.

8.2 Core Entities

person

Field Type Ghi chú
person_id TEXT PK e.g. VNC001
person_name TEXT Tên chính
field TEXT singer / actor / athlete / model / kol / ...
aliases TEXT Pipe-separated
target_final_count INT Default: 30
status TEXT todo / in_progress / done / blocked
accepted_count INT Cập nhật sau mỗi review session
notes TEXT Ghi chú thủ công

candidate

Field Type Ghi chú
candidate_id TEXT PK UUID
person_id TEXT FK
query_id TEXT FK
image_url TEXT
source_page TEXT
thumbnail_url TEXT
provider TEXT serpapi / google_cse
rank INT Rank trong kết quả search
state TEXT State machine
candidate_score REAL 0.0–1.0
created_at DATETIME
updated_at DATETIME

technical_metrics

Field Type
candidate_id TEXT FK
width INT
height INT
format TEXT
file_size_bytes INT
blur_score REAL
sha256 TEXT
technical_pass BOOL

visual_metrics

Field Type
candidate_id TEXT FK
has_person BOOL
person_count INT
main_bbox_ratio REAL
full_body_score REAL
subject_prominence_score REAL
composition_score REAL
diversity_bucket TEXT

review_record

Field Type
candidate_id TEXT FK
review_status TEXT
reject_reason TEXT
reviewer TEXT
reviewed_at DATETIME
notes TEXT

9. Cấu trúc thư mục

project/
├── .env                         ← KHÔNG commit, chứa API keys
├── .env.example                 ← Template public, không có key thật
├── .gitignore                   ← Phải ignore .env và data/raw/
├── README.md
├── requirements.txt
├── config/
│   ├── config.yaml              ← Cấu hình toàn bộ (không có secret)
│   └── domain_blacklist.txt     ← Danh sách domain bị chặn
├── data/
│   ├── roster/
│   │   ├── roster.csv           ← File quản lý nhân vật (edit trực tiếp)
│   │   └── roster_example.csv
│   ├── raw/
│   │   ├── thumbnails/          ← Cache thumbnails (có thể xóa nếu cần)
│   │   └── originals/           ← Ảnh gốc đã download
│   ├── processed/
│   │   ├── review_queue/        ← Shortlist per person (JSON)
│   │   └── exports/             ← Output cuối: ảnh + metadata
│   ├── db/
│   │   └── pipeline.db          ← SQLite database chính
│   └── logs/
│       ├── harvest.log
│       ├── filter.log
│       └── audit.log
├── src/
│   ├── main.py                  ← CLI entry point
│   ├── pipelines/
│   │   ├── harvest_pipeline.py
│   │   ├── filter_pipeline.py
│   │   └── export_pipeline.py
│   ├── modules/
│   │   ├── roster_manager.py
│   │   ├── query_builder.py
│   │   ├── search_connector.py
│   │   ├── result_store.py
│   │   ├── url_prefilter.py
│   │   ├── thumbnail_fetcher.py
│   │   ├── fast_visual_filter.py
│   │   ├── candidate_scorer.py
│   │   ├── download_manager.py
│   │   ├── strict_technical_filter.py
│   │   ├── dedupe_engine.py
│   │   ├── diversity_manager.py
│   │   ├── review_queue_builder.py
│   │   ├── exporter.py
│   │   ├── audit_logger.py
│   │   └── config_manager.py
│   ├── providers/
│   │   ├── base.py              ← Abstract ImageSearchProvider
│   │   ├── serpapi_provider.py
│   │   └── google_cse_provider.py
│   └── ui/
│       └── streamlit_app.py
├── tests/
│   ├── conftest.py
│   ├── test_roster_manager.py
│   ├── test_query_builder.py
│   ├── test_url_prefilter.py
│   ├── test_scoring.py
│   ├── test_dedupe_engine.py
│   └── fixtures/                ← Sample images và mock API responses
└── scripts/
    ├── init_db.py               ← Tạo database lần đầu
    └── reset_person.py          ← Reset state của 1 người về todo

10. Scoring & Threshold Strategy

10.1 Vì sao dùng score thay vì pass/fail cứng

Pass/fail cứng loại quá nhiều ảnh borderline mà reviewer vẫn có thể dùng được. Score giúp:

  • Ưu tiên candidate đáng xem trước (Tier A review trước Tier B)
  • Giữ lại ảnh trung bình để dự phòng khi Tier A chưa đủ
  • Tối ưu số ảnh phải tải và phải review

10.2 Hard gates (bắt buộc pass mới xét tiếp)

min(width, height) > 400 px     → fail = loại ngay
format ∈ {jpg, jpeg, png}       → fail = loại ngay
ảnh đọc được (không corrupt)    → fail = loại ngay
laplacian variance > 80         → fail = loại ngay (configurable)

10.3 Soft scores (ranking)

full_body_score         × 0.35   ← trọng số cao nhất
subject_prominence      × 0.20
resolution_hint         × 0.15
source_quality          × 0.15
composition             × 0.10
query_diversity         × 0.05

10.4 Candidate Tiers

Tier Điều kiện Hành động
A — Priority score ≥ 0.65 + full_body_score ≥ 0.6 Download ngay, review đầu tiên
B — Reserve score ≥ 0.40 Giữ lại, review sau nếu Tier A chưa đủ
C — Auto-reject score < 0.40 hoặc fail hard gate Loại, không review

11. Chiến lược batch 100 người

Không làm từng người từ đầu đến cuối. Thay vào đó chạy breadth-first:

Pass Hành động Lý do
Pass 1 — Harvest all Search toàn bộ 100 người, lưu raw results Nhìn được coverage sớm, phát hiện ai khó tìm ngay
Pass 2 — Fast filter all Thumbnail + visual filter toàn bộ Chạy batch nhanh hơn per-person
Pass 3 — Build shortlists Tạo review queue per person Chuẩn bị cho reviewer
Pass 4 — Manual review Reviewer xem shortlist Đây là bước tốn thời gian nhất của người
Pass 5 — Fill-gap Người chưa đủ → chạy thêm query bổ sung Tập trung resource vào người khó

Lợi ích:

  • Phát hiện sớm ai thiếu ảnh để tăng cường query
  • Không kẹt quá lâu vào 1 người khó tìm
  • Dễ theo dõi tiến độ toàn project

12. Stop Rules

Dừng harvest cho 1 người khi đạt 1 trong các điều kiện:

  • ≥ 35 ảnh provisional pass (Tier A + B), hoặc
  • ≥ 25 ảnh Tier A và ≥ 10 ảnh Tier B, hoặc
  • Reviewer đã accept đủ target_final_count

Không mở rộng thêm candidate khi:

  • Người đã có buffer tốt (đủ Tier A)
  • Toàn bộ query templates đã dùng hết và không có alias mới

Fill-gap trigger:

  • Sau review, accepted_count < target_final_count × 0.8 → sinh thêm queries từ alias hoặc template khác chưa dùng

13. Manual Review Policy

Reviewer chỉ cần trả lời 3 câu hỏi:

  1. Đúng người không? (yes / no → reject_wrong_person)
  2. Ảnh usable không? (yes / no → reject_low_quality / reject_bad_crop / ...)
  3. Quá trùng với ảnh đã accept không? (yes → reject_duplicate_vibe)

Nhãn đầy đủ:

Nhãn Mô tả
accepted Đưa vào dataset
rejected_wrong_person Không phải người cần lấy
rejected_low_quality Mờ, vỡ hạt, ánh sáng xấu
rejected_not_full_body Bị cắt quá nhiều
rejected_duplicate_vibe Quá giống ảnh đã accept (outfit / pose)
rejected_bad_crop Crop sai, mất đầu / chân
rejected_bad_context Ngữ cảnh không phù hợp
saved_raw Giữ link, chưa chắc dùng
unsure Cần xem lại sau

Tốc độ review mục tiêu:

  • Tier A: ~3–5 giây / ảnh (quyết định nhanh)
  • Tier B: ~5–10 giây / ảnh
  • Mục tiêu: reviewer xử lý 40 ảnh shortlist / người trong 5–7 phút

14. Logging & Observability

Log ghi gì:

  • Số query / người, số raw results / query
  • Số candidate pass từng gate (tỷ lệ pass rate)
  • Download errors (URL + HTTP status)
  • Số exact duplicate / near-duplicate loại ra
  • Số ảnh accepted / rejected / saved_raw per person
  • Thời gian xử lý từng phase
  • API quota consumed per day

Dashboard Streamlit nên có:

Widget Nội dung
Progress bar Số người done / total
Table Người đã đủ ảnh / chưa đủ / blocked
Bar chart Tỷ lệ pass qua từng filter
Top sources Domain nào cho ảnh chất lượng cao nhất
Top queries Query template hiệu quả nhất
Daily API usage Quota consumed today

15. Ước tính chi phí & Performance

Chi phí API (SerpAPI — Google Images)

Quy mô Queries Ước tính cost
14 người × 6 query 84 queries ~$0.84 (SerpAPI: ~$0.01/query)
100 người × 6 query 600 queries ~$6.00
100 người × 8 query (fill-gap included) ~800 queries ~$8.00

SerpAPI plan free: 100 searches/tháng. Trả phí từ $50/tháng cho 5,000 searches. Google CSE: 100 queries/ngày miễn phí, sau đó $5 / 1,000 queries.

Ước tính thời gian xử lý (100 người)

Phase Thời gian ước tính
Harvest (600 queries, 30 results each) ~15–30 phút (rate limit)
Fast filter (18,000 thumbnails) ~30–60 phút
Download (~3,000 ảnh pass) ~20–40 phút (4 workers)
Strict filter + dedupe ~10–15 phút
Manual review (100 × 40 ảnh) ~8–10 giờ (reviewer)

Ước tính disk space

Data Dung lượng
Thumbnails (18,000 × ~20KB) ~360 MB
Original images (~3,000 × ~500KB) ~1.5 GB
Final accepted (~3,000 × ~500KB) ~1.5 GB
Database + logs ~50 MB
Tổng ~3.5 GB

16. Công nghệ & Vision Models

Stack chính

Thành phần Lựa chọn
Language Python 3.10+
HTTP httpx (async) hoặc requests
Image processing Pillow, OpenCV
Data pandas, SQLite (built-in)
UI Streamlit
Config PyYAML, python-dotenv
CLI Click hoặc argparse

Vision Models

Tác vụ Model khuyến nghị Ghi chú
Person detection MediaPipe BlazePose (full) Nhẹ, nhanh, chạy CPU được
Person detection (alternative) YOLOv8n (nano) Nếu cần bbox chính xác hơn
Exact dedupe SHA256 Built-in
Near-duplicate pHash (imagehash lib) Hamming distance ≤ 8
Semantic clustering (v2) CLIP embeddings Optional, chỉ cần nếu near-dup không đủ

Lý do chọn MediaPipe BlazePose

  • Chạy được trên CPU, không cần GPU
  • Detect 33 landmarks → đủ để đánh giá full-body
  • Latency ~50–100ms / ảnh trên CPU thông thường
  • Free, không cần API key

Lý do chọn Streamlit cho Review UI

  • Build nhanh, đủ cho grid review
  • Hot reload khi develop
  • Phù hợp internal tool, không cần deploy phức tạp

17. Thứ tự Implement

MVP v1 — Dùng được sớm nhất

# Module Bắt buộc
1 config_manager + .env
2 roster_manager
3 query_builder
4 search_connector (SerpAPI trước)
5 result_store (SQLite)
6 url_prefilter
7 thumbnail_fetcher
8 fast_visual_filter (MediaPipe)
9 candidate_scorer
10 download_manager
11 strict_technical_filter
12 dedupe_engine (Level 1+2)
13 review_queue_builder
14 manual_review_ui (Streamlit)
15 exporter

v1.5 — Tối ưu vận hành

# Module Ưu tiên
16 diversity_manager Cao
17 audit_logger (structured) Cao
18 google_cse_provider (backup) Trung bình
19 Dashboard Streamlit Trung bình

v2 — Nâng chất lượng shortlist

# Tính năng Ghi chú
20 Semantic clustering (CLIP) Giảm ảnh cùng vibe hơn nữa
21 Source reputation model Học từ lịch sử review
22 Adaptive query expansion Tự sinh query mới khi thiếu ảnh
23 Optional identity-assist ranking Dùng face embedding để gợi ý, không quyết định

18. Rủi ro & Mitigation

Rủi ro Mức độ Mitigation
Provider rate limit / thay đổi API Cao Cache raw responses; abstraction layer để đổi provider
Nhiều URL ảnh chết / bị chặn Cao Retry + fallback; lưu source page để reviewer tự mở
Full-body detector bỏ sót hoặc nhận sai Trung bình Chỉ dùng như soft gate; reviewer vẫn là bước cuối
Reviewer mất thời gian vì ảnh trùng Trung bình Dedupe engine tốt + diversity_manager
Metadata lệch với ảnh final Trung bình Exporter và audit_log là nguồn chuẩn; cross-check khi export
IP bị block khi fetch thumbnail Trung bình Jitter giữa requests; tôn trọng robots.txt; không brute-force
API key bị lộ Cao Luôn dùng .env; không commit secrets; .gitignore rõ ràng
Ảnh vi phạm bản quyền / ToS Trung bình Xem Section 20

19. Definition of Done

Một nhân vật được coi là done khi:

  • Có đủ target_final_count ảnh có status accepted
  • Metadata đầy đủ (không thiếu field nào trong schema)
  • Ảnh final đã export ra thư mục exports/{person_id}/
  • Review log có đủ dấu vết (reviewer, timestamp, reason)
  • Không còn candidate ở trạng thái unsure quan trọng chưa xử lý
  • Status trong roster.csv đã cập nhật thành done

Toàn bộ project được coi là done khi:

  • Mọi người trong roster đạt done hoặc blocked (kèm lý do)
  • final_metadata.csv nhất quán với roster và ảnh trên Drive
  • Audit log đủ để truy lại lịch sử xử lý bất kỳ ảnh nào
  • Không có lỗi unresolved trong audit.log

20. Lưu ý Pháp lý & Đạo đức

⚠️ Đọc trước khi sử dụng.

Những gì cần lưu ý:

  1. Google Images Terms of Service: Công cụ này sử dụng API chính thức (SerpAPI / Google CSE), không phải scraping trực tiếp. Tuy nhiên, ảnh thu thập được có thể có bản quyền thuộc về nhiều bên khác nhau.

  2. Mục đích sử dụng: Công cụ này được thiết kế cho mục đích nghiên cứu và xây dựng dataset AI nội bộ. Không sử dụng để phân phối ảnh thương mại hoặc vi phạm bản quyền.

  3. Đối tượng trong ảnh: Tôn trọng quyền riêng tư cá nhân. Không thu thập ảnh có tính chất riêng tư, nhạy cảm hoặc không phù hợp.

  4. Rate limiting & politeness: Không spam API hay server. Tôn trọng robots.txt khi fetch thumbnail trực tiếp. Thêm jitter giữa các request.

  5. Lưu trữ nội bộ: Dataset thu thập chỉ nên dùng nội bộ. Không upload công khai nếu chưa xác minh quyền sở hữu ảnh.


21. Phụ lục — CLI Reference

# Validate roster
python -m src.main validate-roster --roster data/roster/roster.csv

# Harvest tất cả
python -m src.main harvest --roster data/roster/roster.csv

# Harvest 1 người
python -m src.main harvest --person VNC001

# Fast filter
python -m src.main fast-filter --batch all
python -m src.main fast-filter --person VNC001

# Download chỉ ảnh shortlisted
python -m src.main download --only shortlisted
python -m src.main download --only shortlisted --person VNC001 --workers 6

# Strict filter
python -m src.main strict-filter --batch all

# Build review queue
python -m src.main build-review-queue --batch all
python -m src.main build-review-queue --person VNC001 --shortlist-size 40

# Mở UI review
streamlit run src/ui/streamlit_app.py

# Export
python -m src.main export --status accepted
python -m src.main export --person VNC001 --status accepted

# Xem tiến độ
python -m src.main status --batch all
python -m src.main status --person VNC001

# Reset 1 người (về todo, giữ nguyên ảnh đã download)
python scripts/reset_person.py --person VNC001 --keep-downloads

# Khởi tạo database lần đầu
python scripts/init_db.py

22. Phụ lục — Candidate States

new                     ← Vừa lấy từ search API
url_prefilter_rejected  ← Bị loại ở URL prefilter
thumbnail_fetching      ← Đang fetch thumbnail
thumbnail_failed        ← Fetch thumbnail lỗi
thumbnail_ready         ← Có thumbnail local
fast_filter_rejected    ← Bị loại ở fast visual filter
fast_filter_passed      ← Qua fast filter
download_queued         ← Đang chờ download gốc
download_failed         ← Download gốc lỗi
downloaded              ← Đã có ảnh gốc local
technical_rejected      ← Bị loại ở strict technical filter
deduped_out             ← Bị loại vì duplicate
shortlisted             ← Trong review queue
accepted                ← Reviewer accept
rejected                ← Reviewer reject (kèm reason)
saved_raw               ← Giữ link, chưa chắc dùng
unsure                  ← Reviewer chưa quyết định

23. Phụ lục — Config mẫu

# config/config.yaml
# KHÔNG để API key ở đây — dùng .env

search:
  provider: serpapi                  # serpapi | google_cse
  per_query_limit: 30               # số kết quả / query
  queries_per_person: 6             # số query / người (base + field)
  cache_raw_responses: true
  cache_ttl_hours: 72

filter:
  min_side_px: 401                  # strict: min(w,h) > 400
  blur_threshold: 80                # Laplacian variance
  full_body_threshold: 0.55         # full_body_score tối thiểu để pass
  person_bbox_ratio_min: 0.50       # bbox height / image height

dedupe:
  phash_hamming_threshold: 8        # Hamming distance ≤ 8 → near-duplicate

scoring:
  weights:
    full_body: 0.35
    subject_prominence: 0.20
    resolution_hint: 0.15
    source_quality: 0.15
    composition: 0.10
    query_diversity: 0.05
  tier_a_threshold: 0.65
  tier_b_threshold: 0.40

download:
  workers: 4
  timeout_seconds: 20
  max_retries: 3
  backoff_factor: 2.0

review:
  shortlist_per_person: 40
  target_final_per_person: 30

stop_rules:
  max_provisional_pass: 35
  tier_a_sufficient: 25
  tier_b_sufficient: 10

paths:
  thumbnails: data/raw/thumbnails
  originals: data/raw/originals
  exports: data/processed/exports
  db: data/db/pipeline.db
  logs: data/logs

Tóm tắt

Đây là công cụ tăng tốc search + sàng lọc bán tự động, thiết kế để giảm tối đa thao tác tay khi thu thập ảnh người nổi tiếng Việt Nam ở quy mô lớn. Toàn bộ pipeline chạy theo nguyên tắc link-first → cascade filter → score → shortlist, và giữ manual review là lớp kiểm soát chất lượng cuối cùng không thể bỏ qua.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages