How To

Menggunakan .NET / C#

Penggunaan RustODotnet pada aplikasi C# dan .NET di Windows, Linux, dan macOS.

Paket NuGet RustODotnet menyediakan binding C# berkinerja tinggi dan menyertakan runtime native bawaan untuk Windows (x64, arm64), Linux (x64, arm64), dan macOS (x64, arm64).

Instalasi

Pasang paket inti dari NuGet:

dotnet add package RustODotnet

Opsional: pasang paket model resmi untuk menyertakan aset model secara otomatis tanpa konfigurasi manual:

dotnet add package RustODotnet.Models.PPOCRv6.Tiny

1. Siklus Hidup Mesin & Inisialisasi

RustO mengelola pointer memori native unmanaged melalui IDisposable. Selalu gunakan pernyataan using atau lakukan Dispose() saat instans tidak lagi digunakan:

using System;
using RustODotnet;

// 1. Inisialisasi menggunakan model bawaan default PP-OCRv6
using var ocr = RustO.Initialize();

// Atau tentukan path model kustom secara eksplisit:
var customConfig = new InitializeConfig
{
    Template = "ppv6",
    Detection = new DetectionConfig { ModelPath = "models/det.rten", LimitSideLen = 736 },
    Recognition = new RecognitionConfig
    {
        ModelPath = "models/rec.rten",
        DictPath = "models/dict.txt"
    }
};

using var customOcr = RustO.Initialize(customConfig);

2. Opsi Permintaan Lokal (OcrRunOptions)

Konfigurasikan opsi per panggilan deteksi tanpa perlu mengalokasikan ulang sesi inferensi:

var options = new OcrRunOptions
{
    Output = OutputGranularity.Lines, // Lines, Words, atau Spatial
    LineYThreshold = 0.5f,
    WordXThreshold = 0.4f,
    TextScore = 0.55f,
    MaxSideLen = 1600f,
    Detection = new DetectionRunOptions
    {
        LimitSideLen = 960,
        LimitType = "max"
    },
    Postprocess = new PostprocessRunOptions
    {
        UseDilation = true,
        UnclipRatio = 2.0f
    }
};

3. Sumber Gambar yang Didukung

ImageSource menerima path berkas/URI atau larik byte dalam memori RAM:

using System.IO;

// 1. Path filesystem atau file:// URI
var uriSource = new UriImageSource("invoices/sample.jpg");

// 2. Larik byte dalam memori (misal dari stream atau ASP.NET Core IFormFile)
byte[] imageBytes = await File.ReadAllBytesAsync("invoices/sample.jpg");
var bytesSource = new BytesImageSource(imageBytes);

4. Contoh Praktis & Penanganan Keluaran

Contoh A: Deteksi Baris Terstruktur dengan Koordinat Frame

using System;
using RustODotnet;

using var ocr = RustO.Initialize();
var result = ocr.DetectText(new UriImageSource("receipt.jpg"));

if (result is StructuredDetectTextResult structured)
{
    Console.WriteLine($"Ditemukan {structured.Items.Count} baris teks:\n");
    foreach (var item in structured.Items)
    {
        Console.WriteLine($"[{item.Frame.Left:F0}, {item.Frame.Top:F0}, {item.Frame.Width:F0}x{item.Frame.Height:F0}]");
        Console.WriteLine($"  Teks: {item.Text}");
        Console.WriteLine($"  Skor: {item.Score:P1}");
    }
}

Contoh Keluaran:

Ditemukan 3 baris teks:

[40, 30, 200x24]
  Teks: TOKO MAJU JAYA - PUSAT
  Skor: 99.1%
[40, 75, 150x20]
  Teks: Subtotal: Rp450.000
  Skor: 98.4%
[40, 105, 150x20]
  Teks: Total:    Rp495.000
  Skor: 99.5%

Contoh B: Mengekstrak Tabel Dokumen ke Tata Letak Spasial

using System;
using RustODotnet;

using var ocr = RustO.Initialize();

var spatialOptions = new OcrRunOptions
{
    Output = OutputGranularity.Spatial,
    LineYThreshold = 0.5f,
    WordXThreshold = 0.4f
};

var spatialResult = ocr.DetectText(new UriImageSource("invoice_table.png"), spatialOptions);

if (spatialResult is SpatialDetectTextResult spatial)
{
    Console.WriteLine("--- Teks Spasial Hasil Rekonstruksi ---");
    Console.WriteLine(spatial.Text);
}

Contoh Keluaran:

--- Teks Spasial Hasil Rekonstruksi ---
Deskripsi Layanan        Jumlah       Tarif        Subtotal
Jasa Konsultasi               8   Rp1.500.000  Rp12.000.000
Lisensi Perangkat Lunak       1   Rp4.990.000   Rp4.990.000
Hosting Cloud                 1     Rp500.000     Rp500.000
───────────────────────────────────────────────────────────
Total Pembayaran:                              Rp17.490.000

Contoh C: Implementasi Controller ASP.NET Core Web API

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using RustODotnet;
using System.IO;
using System.Threading.Tasks;

[ApiController]
[Route("api/[controller]")]
public class OcrController : ControllerBase
{
    private readonly RustO _ocr;

    public OcrController()
    {
        // Pada aplikasi web, inisialisasi satu kali sebagai service singleton / scoped
        _ocr = RustO.Initialize();
    }

    [HttpPost("scan")]
    public async Task<IActionResult> ScanDocument(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("Tidak ada berkas gambar yang diunggah.");

        using var memoryStream = new MemoryStream();
        await file.CopyToAsync(memoryStream);

        var result = _ocr.DetectText(
            new BytesImageSource(memoryStream.ToArray()),
            new OcrRunOptions { Output = OutputGranularity.Spatial }
        );

        if (result is SpatialDetectTextResult spatial)
        {
            return Ok(new { text = spatial.Text });
        }

        return StatusCode(500, "Pemrosesan OCR gagal.");
    }
}