Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

NEVU

Deteksi & lokalisasi pemalsuan ijazah, transkrip, dan sertifikat kompetensi Indonesia
Machine learning untuk dokumen legacy · blockchain anchoring untuk dokumen terverifikasi

status phase python tests license


Daftar isi


Masalah

Pemalsuan ijazah di Indonesia bukan kasus pinggiran — ia punya pasar, harga, dan rantai pasok sendiri. Dua hal membuatnya sulit dilawan:

  1. Dokumen legacy tidak punya jejak digital. Puluhan juta ijazah terbit sebelum sistem verifikasi apa pun ada. Tidak ada hash, tidak ada tanda tangan digital, tidak ada QR. Yang tersisa hanya citra — foto atau hasil scan.
  2. Verifikasi manual tidak menskala. HRD menerima ratusan lamaran; memeriksa satu per satu ke registry institusi tidak realistis, dan banyak institusi tidak punya endpoint verifikasi sama sekali.

Sementara itu, alat pemalsuan makin murah: inpainting berbasis diffusion bisa mengganti nama atau nilai pada scan dengan mulus, tanpa keahlian desain.

Pendekatan

NEVU menjawab dua sisi masalah dengan dua jalur yang saling mengisi:

Jalur ML (inti) Jalur blockchain (bungkus)
Untuk dokumen lama yang hanya ada sebagai citra dokumen yang sudah lolos verifikasi
Menjawab "apakah citra ini menunjukkan tanda manipulasi, dan di mana?" "apakah dokumen ini tercatat, oleh siapa, kapan, dan masih berlaku?"
Keluaran skor probabilistik + heatmap + field OCR hash on-chain + status (aktif / dicabut)
Sifat probabilistik — alat triase deterministik — catatan permanen

Important

Model menghasilkan probabilitas; blockchain menyimpan pencatatan. Skor ML tidak pernah ditulis on-chain sebagai kebenaran. Yang di-anchor hanya dokumen yang sudah di-approve oleh manusia atau institusi penerbit. Ini menjaga agar ketidakpastian statistik tidak berubah jadi klaim permanen.

Urutan pembangunan bersifat mengikat: kualitas model dulu (M0–M2), aplikasi kemudian (M3–M5). app/ dan chain/ tidak dikerjakan sebelum gate akurasi M2 terlampaui dan dilaporkan apa adanya.

Status proyek

Milestone Isi Status
M0 Fondasi repo, generator dataset sintetis + ground-truth mask, splits, dataset card
M1 Model v1 (image-level) & v2 (+lokalisasi), baseline ELA/CNN, leaderboard.md
M2 Cabang OCR + fusi multimodal, ablation, robustness — gate F1 ≥ 0.90
M3 Backend FastAPI /predict (skor + heatmap + OCR) 🔒
M4 NevuRegistry.sol, deploy testnet, /anchor + /verify 🔒
M5 Frontend Next.js, Verify Page + QR, docker compose up 🔒

🔒 = terkunci sampai gate M2 lolos. app/ dan chain/ sengaja masih kosong.

Arsitektur

        ┌──────────────── FASE 1 — ML (inti) ────────────────┐
        │                                                     │
Upload  │   Preprocess ──┬── Visual branch (ELA/SRM + CNN) ─┐ │  score
dokumen │   (deskew,     │                                  │ │  + heatmap
  ─────►│    normalize)  ├── Localization head (U-Net/FPN) ─┼─┼──► + field OCR
        │                │                                  │ │
        │                └── Text branch (OCR + konsistensi ─┘ │
        │                    tipografi/format)      → Fusion   │
        └─────────────────────────────────────────────────────┘
                                   │
                          FastAPI  │  POST /predict
                                   ▼
        ┌──────────────── FASE 2 — dApp (bungkus) ───────────┐
        │  Next.js frontend                                   │
        │    upload → hasil ML → [Amankan ke blockchain]       │
        │                             │ POST /anchor          │
        │                             ▼                        │
        │  NevuRegistry.sol  ──── keccak256(dokumen)  ──► ⛓  │
        │    anchor / revoke / getStatus                testnet│
        │                             ▲                        │
        │  Verify Page (publik, tanpa login) ── GET /verify ───┘
        │    scan QR / paste hash → status tercatat            │
        └─────────────────────────────────────────────────────┘

Pemisahan yang dijaga ketat di UI: "hasil analisis ML (perkiraan)" dan "status tercatat di blockchain (fakta pencatatan)" ditampilkan sebagai dua blok terpisah dengan bahasa berbeda. Tidak ada cap "ASLI"/"PALSU" mutlak.


Quickstart

Prasyarat: Python 3.9+ (3.11 direkomendasikan), ~500 MB ruang disk untuk dataset default.

git clone https://github.com/itsnevu/credential-forgery-detection.git
cd credential-forgery-detection

python3 -m venv --system-site-packages .venv
.venv/bin/pip install -r ml/requirements.txt

# 1. generate dataset (400 sampel, seed 1337, ±2 menit)
.venv/bin/python -m ml.src.forge.generate

# 2. lihat hasilnya — contact sheet dengan mask di-overlay merah
.venv/bin/python -m ml.src.forge.viz --n 12
open ml/datasets/nevu_v0/preview.png

# 3. jalankan test
.venv/bin/python -m pytest ml/tests -q

Dataset yang dihasilkan ada di ml/datasets/nevu_v0/ (gitignored):

nevu_v0/
├── images/000000.jpg …      # citra dokumen (asli & palsu)
├── masks/000000.png …       # ground-truth mask biner per piksel
├── labels.jsonl             # satu record per sampel
├── splits.json              # train / val / test / test_cross_source / test_genai
├── stats.json               # ringkasan komposisi
└── config.used.yaml         # config persis yang menghasilkan dataset ini

Satu record labels.jsonl:

{
  "id": "000042",
  "image": "images/000042.jpg",
  "mask": "masks/000042.png",
  "label": 1,
  "template": "ijazah_classic",
  "op": "text_replace",
  "aug": "phone",
  "split": "train",
  "fields": { "nama": "Indah Suryani, S.E.", "institusi": "Universitas Tirta Kencana",
              "tahun": "2019", "nomor": "412/UN/B/2019", "program": "Manajemen",
              "kota": "Medan" },
  "forgery": { "op": "text_replace", "ok": true, "field": "program",
               "old": "Akuntansi", "new": "Manajemen", "font_changed": false }
}

fields adalah ground truth untuk evaluasi OCR di M2; forgery mencatat persis apa yang diubah, sehingga metrik bisa dipecah per tipe serangan.


Dataset nevu_v0

Belum ada dataset publik berisi ijazah/transkrip/sertifikat Indonesia dengan mask pemalsuan per piksel. Dokumen asli tidak bisa dikumpulkan dan dirilis tanpa membocorkan data pribadi (UU PDP No. 27/2022). Karena itu nevu_v0 dibangkitkan sepenuhnya: dokumen bersih dirender, bukan dikumpulkan — ground truth diketahui persis, dan tidak ada orang sungguhan di dalamnya.

Contoh sampel dataset dengan mask di-overlay merah
Contact sheet: area merah = ground-truth mask. Label menunjukkan ASLI/PALSU, operasi pemalsuan, kondisi tangkap, template family, dan split.

Komposisi (run default, 400 sampel)

Dimensi Distribusi
Label asli 203 · palsu 197
Template ijazah_classic 125 · transkrip 96 · ijazah_modern 92 · sertifikat_lsp 87
Operasi text_replace 62 · font_substitution 41 · splice 37 · copy_move 32 · local_recompress 25
Kondisi scan 113 · phone 108 · clean 102 · recompressed 77
Split train 221 · test_cross_source 87 · test 53 · val 39

Template family

Setiap family adalah sumber yang berbeda — beda tipografi, tata letak, ornamen, dan ukuran halaman. Ini yang membuat uji generalisasi cross-source bermakna.

Family Jenis Halaman Karakteristik
ijazah_classic Ijazah Potret 1000×1400 Border ganda, stempel bundar, tanda tangan, serif, rata tengah
ijazah_modern Ijazah Potret 1000×1400 Minimalis, ornamen sudut, field berlabel, sans + mono, rata kiri
transkrip Transkrip akademik Potret 1000×1400 Tabel mata kuliah / SKS / nilai, garis pemisah, IPK
sertifikat_lsp Sertifikat kompetensi Lanskap 1400×1000 Format BNSP/LSP, masa berlaku, campuran serif & sans

Dokumen dirender di atas kertas prosedural: warna dasar + noise frekuensi rendah (serat) + noise halus. Latar yang benar-benar rata akan membuat splicing terdeteksi secara trivial dan menggelembungkan semua metrik.


Operasi pemalsuan

Setiap operasi di ml/src/forge/ops.py mematuhi kontrak yang sama:

input: Document bersih (citra + kotak field) output: (citra RGB, mask uint8 0/255, info dict) invarian: mask menutupi setiap piksel yang mungkin diubah operasi itu

Invarian ini diuji (test_op_changes_image_and_mask_covers_change, kebocoran < 1%). Kalau sebuah operasi menyentuh piksel di luar mask-nya, segmentation head akan belajar mengabaikan bukti yang nyata.

Operasi Mekanisme Kenapa ada di set ini
text_replace (2×) Hapus satu field, sintesis kertas pengganti dari cincin di sekitarnya, gambar ulang teks berbeda. 35% kemungkinan memakai sibling font Serangan yang benar-benar penting: ganti nama, nilai, tahun, nomor
copy_move Duplikasi satu region ke tempat lain di halaman yang sama (skala ±8%, rotasi ±2.5°) Sumber & target berbagi riwayat noise/JPEG yang sama — menuntut deteksi korelasi, bukan sekadar anomali
splice Tempel region dari dokumen lain, 50% dengan pencocokan tone Komposisi lintas dokumen; pemalsu yang teliti akan menyamakan warna
font_substitution String yang sama, face berbeda dan/atau tracking diubah Kelas paling halus — menguji penalaran konsistensi tipografi, bukan artefak piksel
local_recompress Encode ulang satu region pada kualitas JPEG lebih rendah Jejak kompresi ganda tanpa perubahan semantik — mendeteksi "region ini pernah disentuh"

Kenapa text_replace dibobot 2×: pada ijazah, serangan yang punya nilai ekonomi hampir selalu penggantian teks. Copy-move dan splicing lebih umum di literatur forensik citra alam, tapi lebih jarang dipakai pada dokumen.

Detail inpainting. _background() tidak mengisi kotak dengan warna solid — itu akan jadi artefak yang bisa "dihafal" model sebagai jalan pintas. Sebaliknya ia mengambil cincin piksel di sekeliling field, memakai persentil ke-70 kecerahannya sebagai warna kertas, lalu menambahkan noise gaussian yang sepadan.


Kondisi tangkap (augmentasi)

Diterapkan setelah pemalsuan, karena begitulah urutannya di dunia nyata: dokumen dipalsukan, lalu dicetak/di-scan/difoto. Setiap fungsi menerima dan mengembalikan (citra, mask) — langkah geometrik mentransportasikan mask dengan resampling nearest-neighbour, dan mask di-binerisasi ulang di akhir.

Pipeline Rantai Mensimulasikan
clean JPEG tunggal PDF/ekspor digital langsung
scan downscale→upscale, kontras, noise sensor, JPEG ×2 Cetak lalu scan; kehilangan resolusi + kompresi berulang
phone warp perspektif, gradien cahaya, blur, noise, JPEG Foto kamera HP: miring, satu sumber cahaya, fokus tidak sempurna
recompressed JPEG ×3 Dokumen yang beredar lewat WhatsApp/email berkali-kali

Kondisi tangkap adalah bagian tersulit dari masalah ini: kompresi dan resampling menghapus persis jejak forensik yang ingin dideteksi model. Sebuah detektor yang hanya bagus pada clean tidak berguna di lapangan.


Split & protokol evaluasi

Ditulis ke splits.json:

Split Isi Fungsi
train / val / test In-distribution, dari 3 family non-holdout Pengembangan & metrik utama
test_cross_source Seluruh sampel family yang di-holdout (default sertifikat_lsp) Generalisasi ke layout, font, dan ukuran halaman yang tidak pernah dilihat saat latih
test_genai Kosong di M0 Ketahanan terhadap pemalsuan generatif (inpainting/diffusion)

Penugasan split adalah hash dari indeks sampel, bukan pengacakan sekali jalan. Konsekuensinya: sampel tetap berada di split yang sama ketika n_samples diubah — kamu bisa menaikkan ukuran dataset tanpa mencemari test set dengan sampel yang dulu ada di train. Ini diuji (test_split_assignment_is_stable_across_dataset_size).

Sampel split cross-source
test_cross_source — family sertifikat_lsp, lanskap, layout dan font yang tidak ada di training.

Warning

test_genai sengaja dibiarkan kosong di M0. Tidak ada model generatif di pipeline saat ini, dan mengisinya dengan pemalsuan buatan sendiri yang disebut "GenAI" akan menghasilkan angka robustness yang menyesatkan. Letakkan berkas di ml/data/genai_dropin/ untuk di-ingest pada M2. Jangan laporkan angka ketahanan GenAI sebelum split ini terisi.

Metrik yang akan dilaporkan (M1–M2)

  • Deteksi (level dokumen): Accuracy, Precision, Recall, F1, AUC-ROC
  • Lokalisasi (level piksel): IoU, F1-piksel
  • Robustness: delta metrik per pipeline augmentasi dan pada test_cross_source
  • Per-serangan: rincian recall untuk tiap operasi — angka agregat menyembunyikan kelemahan pada kelas halus seperti font_substitution

Gate M2: F1 ≥ 0.90 pada test in-distribution dan laporan jujur penurunan pada cross-source & GenAI. Fase 2 tidak dimulai sebelum keduanya terpenuhi.


Reproduktibilitas

Tiga jaminan, semuanya ditegakkan lewat test:

  1. RNG per sampel. Setiap sampel menurunkan generatornya sendiri dari SeedSequence([seed, index]). Sampel ke-i byte-identik terlepas dari ukuran dataset atau urutan pembangkitan. Tidak ada state global yang bocor antar sampel.
  2. Config ikut disimpan. Setiap run menyalin config yang sudah di-resolve ke config.used.yaml di sebelah data. Sebuah dataset selalu bisa dilacak balik ke setelan persis yang menghasilkannya.
  3. Split stabil. Berbasis hash indeks, bukan shuffle — lihat bagian di atas.
# dua perintah ini menghasilkan berkas yang identik bit demi bit
.venv/bin/python -m ml.src.forge.generate --seed 1337 --n 50 --out /tmp/a
.venv/bin/python -m ml.src.forge.generate --seed 1337 --n 50 --out /tmp/b
diff -r /tmp/a/images /tmp/b/images && echo "identik"

Note

Satu sumber non-determinisme lintas mesin: kumpulan font sistem. Generator memakai font yang tersedia di host (macOS /System/Library/Fonts/Supplemental, Linux DejaVu/Liberation). Mesin dengan font lebih sedikit menghasilkan keragaman tipografi lebih rendah, dan font_substitution bisa merosot jadi perubahan tracking saja. Catat kumpulan font kamu saat membandingkan run antar-mesin.


Konfigurasi

ml/configs/forge_default.yaml — semua yang bisa disetel:

seed: 1337
n_samples: 400
out_dir: ml/datasets/nevu_v0

forged_frac: 0.5                  # proporsi sampel yang dipalsukan

cross_source_families:            # family yang di-holdout sepenuhnya
  - sertifikat_lsp
cross_source_frac: 0.2            # seberapa sering menarik dari family holdout

val_frac: 0.15
test_frac: 0.15

op_weights:                       # bobot relatif, dinormalisasi otomatis
  text_replace: 2.0               # serangan yang paling penting
  copy_move: 1.0
  splice: 1.0
  font_substitution: 1.0
  local_recompress: 0.6

aug_weights:
  clean: 1.0
  scan: 1.2
  phone: 1.2
  recompressed: 0.8

max_side: 1000                    # sisi terpanjang setelah resize
save_quality: 92

Override lewat CLI tanpa mengedit berkas:

.venv/bin/python -m ml.src.forge.generate --n 5000 --seed 42 --out ml/datasets/nevu_v1
Flag Fungsi
--config Path config YAML (default ml/configs/forge_default.yaml)
--n Override n_samples
--seed Override seed
--out Override out_dir

Untuk training M1 naikkan n_samples secara signifikan — 400 hanya cukup untuk memvalidasi pipeline. Sekitar 5.000 sampel butuh ±25 menit satu proses.


Testing

.venv/bin/python -m pytest ml/tests -q      # 20 passed, ±25 detik

Test-nya bukan basa-basi — mereka menjaga dua properti yang menjadi tumpuan seluruh proyek:

Test Menjaga
test_op_changes_image_and_mask_covers_change Mask ⊇ piksel yang berubah, per operasi, kebocoran < 1%. Ini kontrak ground truth lokalisasi
test_sample_is_deterministic_by_index Sampel ke-i identik pada seed yang sama
test_template_is_deterministic Renderer tidak punya state tersembunyi
test_split_assignment_is_stable_across_dataset_size Menambah data tidak mencemari test set
test_held_out_family_only_appears_in_cross_source_split Kebocoran cross-source mustahil secara konstruksi
test_mask_is_binary_after_augmentation Mask tetap {0,255} melalui semua pipeline geometrik
test_clean_document_has_empty_mask Sampel asli tidak punya mask palsu-positif
test_no_pii_in_corpus_meta Klaim "tidak ada data pribadi" terperiksa secara mekanis

Struktur repositori

credential-forgery-detection/
├── ml/                             # FASE 1 — inti
│   ├── configs/
│   │   └── forge_default.yaml      # config eksperimen berversi
│   ├── data/
│   │   ├── dataset_card.md         # asal, komposisi, batasan, etika
│   │   └── genai_dropin/           # slot sampel GenAI (diisi M2)
│   ├── datasets/                   # hasil generate — gitignored
│   ├── src/forge/
│   │   ├── corpus.py               # kosakata Indonesia sintetis (audit "no PII")
│   │   ├── fonts.py                # resolusi font + pemilihan sibling face
│   │   ├── render.py               # primitif gambar: kertas, border, stempel, teks ber-tracking
│   │   ├── templates.py            # 4 template family
│   │   ├── ops.py                  # 5 operasi pemalsuan + mask
│   │   ├── augment.py              # 4 pipeline kondisi tangkap
│   │   ├── generate.py             # orkestrasi CLI + penulisan split
│   │   └── viz.py                  # contact sheet dengan overlay mask
│   ├── benchmark/                  # M1: skrip eval + leaderboard.md
│   ├── tests/                      # 20 test
│   └── requirements.txt
├── app/                            # M3–M5: FastAPI backend + Next.js frontend
├── chain/                          # M4: NevuRegistry.sol + deploy testnet
├── docs/                           # aset README
└── README.md

Setiap modul di src/forge/ berkisar 70–210 baris dan punya satu tanggung jawab. Keputusan non-obvious ditandai komentar # why: di kode.


Roadmap

M1 — Model v1/v2 + evaluasi

Backbone (EfficientNet/ResNet via timm) di atas jejak forensik (ELA, noise residual, filter SRM) untuk klasifikasi level dokumen; lalu segmentation head (U-Net/FPN) untuk heatmap piksel. Baseline pembanding: ELA + classifier klasik, CNN vanilla. Keluaran: benchmark/leaderboard.md berisi angka nyata.

M2 — Multimodal + gate akurasi

Cabang teks: OCR Bahasa Indonesia (PaddleOCR/Tesseract) → fitur konsistensi tipografi, alignment baris, validitas format nomor/tanggal → fusi dengan cabang visual. Ablation (visual-only / teks-only / fusi) untuk membuktikan tiap komponen membayar biayanya. Uji robustness + ingest test_genai. Gate: F1 ≥ 0.90 in-distribution + laporan jujur cross-source & GenAI.

M3 — Backend inference

FastAPI POST /predict memuat model terekspor (TorchScript/ONNX) → { score, heatmap_png_base64, ocr_fields, verdict_hint }.

M4 — Smart contract

NevuRegistry.sol di EVM testnet (Base Sepolia / Polygon Amoy, swappable via env):

function anchor(bytes32 docHash, bytes32 metaHash) external;
function revoke(bytes32 docHash) external;
function getStatus(bytes32 docHash) external view
    returns (bool exists, bool revoked, uint256 ts, address issuer);

event Anchored(bytes32 indexed docHash, address indexed issuer, uint256 ts);
event Revoked(bytes32 indexed docHash, uint256 ts);

Append-only, hanya hash — tidak ada data pribadi on-chain. Gas dibayar akun relayer aplikasi, sehingga pengguna tidak perlu punya kripto atau wallet.

M5 — dApp + demo publik

Next.js: upload → skor + overlay heatmap + field OCR → "Amankan ke blockchain" → Verify Page publik tanpa login (paste hash atau scan QR). docker compose up menyalakan Postgres + backend + frontend. Target: clone segar sampai demo jalan dalam 60 detik.

Di luar cakupan MVP

Mainnet produksi · verifikasi fitur fisik (hologram, mikroprint, UV) · integrasi resmi PDDikti/BNSP (hanya disediakan hook) · skalabilitas enterprise.


Batasan & risiko

Bagian ini sengaja ditulis lebih panjang daripada bagian klaim.

Deteksi bersifat probabilistik, bukan penentuan. Keluaran model adalah skor dan heatmap. Ia mempersempit tumpukan dokumen yang perlu diperiksa manusia. Ia bukan bukti hukum, dan UI tidak boleh menampilkannya sebagai cap "ASLI"/"PALSU".

Dataset masih sepenuhnya sintetis. Dokumen yang dirender bukan kertas yang difoto. Scan nyata membawa halftone, tekstur serat, rembesan tinta, dan dithering printer yang hanya didekati oleh kertas prosedural kami. Angka pada nevu_v0 adalah batas atas dan tidak boleh dikutip sebagai akurasi lapangan.

Mask berbentuk kotak. Mask adalah bounding box region yang diedit, bukan mask ketat pada level glyph. IoU piksel karena itu diukur terhadap target yang sedikit longgar; perlakukan sebagai perkiraan.

Kumpulan font tergantung host. Lihat catatan di Reproduktibilitas.

Arms race dengan GenAI. Pemalsuan berbasis diffusion berkembang lebih cepat daripada detektor. Split test_genai ada supaya penurunan performa terlihat, bukan tersembunyi di balik angka agregat. Model apa pun yang dilatih di sini akan menua dan perlu dilatih ulang.

Model bisa salah ke dua arah. False positive menuduh pemegang ijazah asli; false negative meloloskan yang palsu. Keduanya punya biaya nyata dan tidak simetris tergantung pemakaian. Threshold operasional harus dipilih per konteks, bukan ditetapkan sekali di kode.

Blockchain tidak memverifikasi kebenaran. Anchoring membuktikan sebuah hash tercatat pada waktu tertentu oleh alamat tertentu. Ia tidak membuktikan dokumen itu benar — hanya bahwa ia dicatat. Kualitas jaminan sepenuhnya bergantung pada siapa yang berhak melakukan anchor.

Kebenaran akademik faktual di luar cakupan. Apakah orang ini benar kuliah di sana adalah pertanyaan untuk registry institusi (hook cross-check), bukan untuk model forensik citra.


Etika, privasi & lisensi

Research-only. Generator ini ada untuk melatih detektor. Ia sengaja tidak memuat teknik dan penyetelan kualitas yang akan membuat keluarannya berguna untuk benar-benar menipu verifier manusia. Isu, PR, dan diskusi yang mengarah ke peningkatan kualitas pemalsuan di luar kebutuhan deteksi tidak akan dilayani.

Tidak ada data pribadi. Semua nama, institusi, nomor, dan tanggal adalah rekaan. Seluruh kosakata ada di ml/src/forge/corpus.py dan bisa diperiksa siapa pun. Nama institusi tidak berkorespondensi dengan universitas atau LSP nyata mana pun di Indonesia. Klaim ini ditegakkan oleh test.

UU PDP No. 27/2022. Tidak ada data pribadi yang ditulis on-chain — hanya hash dokumen. Metadata off-chain disimpan di Postgres di bawah kendali operator, bukan di ledger publik yang tidak bisa dihapus.

Artefak tidak diredistribusi. Citra hasil generate ada di .gitignore. Bangkitkan ulang dari config, jangan sebarkan berkasnya.

Lisensi: research-only sampai ditentukan lain. Lihat ml/data/dataset_card.md §6.


FAQ

Kenapa ML dulu, blockchain belakangan? Karena blockchain adalah bagian yang mudah. Anchoring hash ke smart contract adalah pekerjaan beberapa hari dan sudah dipecahkan berkali-kali. Yang belum dipecahkan — dan yang menentukan apakah proyek ini berguna — adalah mendeteksi manipulasi pada citra dokumen legacy. Membangun dApp lebih dulu akan menghasilkan demo yang mengesankan di atas model yang tidak berfungsi.

Kenapa dataset sintetis, bukan dokumen nyata? Ijazah nyata memuat data pribadi. Mengumpulkan dan merilisnya melanggar UU PDP, dan tanpa rilis tidak ada reproduktibilitas. Sintesis juga memberi ground-truth mask yang persis — sesuatu yang mustahil didapat dari dokumen nyata tanpa pelabelan manual yang mahal dan tetap perkiraan. Konsekuensinya (gap sintetis → nyata) dicatat terbuka di Batasan.

Kenapa skor ML tidak disimpan on-chain? Karena blockchain bersifat permanen dan skor ML bersifat sementara. Model versi berikutnya akan memberi skor berbeda untuk dokumen yang sama. Menuliskan probabilitas ke ledger yang tidak bisa diubah membekukan ketidakpastian menjadi klaim, dan tidak ada cara memperbaikinya nanti.

Apakah ini bisa dipakai produksi sekarang? Belum. M0 baru menghasilkan dataset. Tidak ada model terlatih, tidak ada API, tidak ada kontrak. Ikuti tabel Status proyek.

Bisa dipakai untuk jenis dokumen lain? Arsitekturnya umum — tambahkan template family di templates.py dan operasi pemalsuan mengikuti otomatis. Yang spesifik Indonesia hanya kosakata dan format nomor.

Butuh GPU? Tidak untuk M0 — generator berjalan di CPU. M1 dan seterusnya butuh GPU untuk training dalam waktu wajar.

About

Open-source ML + blockchain for verifying Indonesian diplomas & competency certificates: a multimodal model detects & localizes document forgery; verified docs anchored on-chain.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages