Panduan Lengkap DETR: Object Detection dengan Transformers

# Panduan Lengkap DETR: Object Detection dengan Transformers DETR (DEtection TRansformer) adalah pendekatan revolusioner untuk object detection yang dikembangkan oleh Facebook AI Research. DETR mengg...

By Ruby Abdullah · · tutorial
PythonDETRObject DetectionTransformerComputer Vision

Panduan Lengkap DETR: Object Detection dengan Transformers

DETR (DEtection TRansformer) adalah pendekatan revolusioner untuk object detection yang dikembangkan oleh Facebook AI Research. DETR menggantikan pipeline tradisional yang kompleks dengan arsitektur Transformer yang elegan dan end-to-end.

Dalam tutorial ini, kita akan mempelajari DETR dari konsep dasar hingga implementasi praktis untuk object detection dan segmentation.

Mengapa DETR?

Keunggulan DETR:

  • End-to-End: Tidak memerlukan Non-Maximum Suppression (NMS) atau anchor boxes
  • Simplicity: Inference hanya membutuhkan ~50 baris kode PyTorch
  • Performance: Menyamai Faster R-CNN dengan setengah computation power
  • Versatile: Mendukung object detection dan panoptic segmentation
  • Global Reasoning: Transformer memungkinkan reasoning global tentang relasi objek
  • Parallel Prediction: Prediksi paralel membuat DETR sangat cepat
  • Perbandingan dengan Metode Tradisional:

    | Aspek | Traditional (Faster R-CNN) | DETR |

    |-------|---------------------------|------|

    | Anchor Boxes | Ya | Tidak |

    | NMS Post-processing | Ya | Tidak |

    | Hand-crafted Components | Banyak | Minimal |

    | End-to-End Training | Tidak | Ya |

    | Global Context | Terbatas | Penuh |

    Arsitektur DETR

    Komponen Utama:

    Input Image → CNN Backbone → Transformer Encoder → Transformer Decoder → FFN → Predictions
    

    ↓ ↓ ↓

    Features Positional Object Queries

    Encoding (Learned)

    1. CNN Backbone

    # ResNet-50 atau ResNet-101 sebagai feature extractor
    

    Input: Image (3, H, W)

    Output: Feature map (2048, H/32, W/32)

    2. Transformer Encoder

    # Memproses flattened feature map dengan self-attention
    

    Menambahkan positional encoding

    Output: Encoded features dengan global context

    3. Transformer Decoder

    # Menggunakan learned object queries (default: 100)
    

    Cross-attention dengan encoded features

    Self-attention antar object queries

    Output: 100 embeddings untuk prediksi

    4. Prediction Heads

    # FFN untuk class prediction
    

    FFN untuk bounding box prediction (centerx, centery, width, height)

    Special class: "no object" untuk query yang tidak mendeteksi objek

    Instalasi

    Requirements

    # Clone repository
    

    git clone https://github.com/facebookresearch/detr.git

    cd detr

    Install dependencies

    conda create -n detr python=3.8

    conda activate detr

    PyTorch dan Torchvision

    conda install pytorch torchvision cudatoolkit=11.3 -c pytorch

    Dependencies lainnya

    conda install cython scipy

    pip install -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'

    Untuk panoptic segmentation (optional)

    pip install git+https://github.com/cocodataset/panopticapi.git

    Verifikasi Instalasi

    import torch
    

    import torchvision

    print(f"PyTorch version: {torch.version}")

    print(f"Torchvision version: {torchvision.version}")

    print(f"CUDA available: {torch.cuda.isavailable()}")

    Quick Start: Inference dengan Pretrained Model

    1. Load Model via PyTorch Hub

    import torch
    

    from PIL import Image

    import requests

    import matplotlib.pyplot as plt

    Load pretrained DETR model

    model = torch.hub.load('facebookresearch/detr:main', 'detrresnet50', pretrained=True)

    model.eval()

    COCO classes

    CLASSES = [

    'N/A', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',

    'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A',

    'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse',

    'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack',

    'umbrella', 'N/A', 'N/A', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',

    'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove',

    'skateboard', 'surfboard', 'tennis racket', 'bottle', 'N/A', 'wine glass',

    'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich',

    'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake',

    'chair', 'couch', 'potted plant', 'bed', 'N/A', 'dining table', 'N/A',

    'N/A', 'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',

    'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'N/A',

    'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'

    ]

    Colors untuk visualisasi

    COLORS = [[0.000, 0.447, 0.741], [0.850, 0.325, 0.098], [0.929, 0.694, 0.125],

    [0.494, 0.184, 0.556], [0.466, 0.674, 0.188], [0.301, 0.745, 0.933]]

    2. Preprocessing dan Inference

    import torchvision.transforms as T
    
    

    Standard COCO transforms

    transform = T.Compose([

    T.Resize(800),

    T.ToTensor(),

    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

    ])

    def detect(imagepath, model, transform, threshold=0.7):

    """

    Detect objects in an image using DETR.

    Args:

    imagepath: Path to image or URL

    model: DETR model

    transform: Image transforms

    threshold: Confidence threshold

    Returns:

    Detected objects with boxes and labels

    """

    # Load image

    if imagepath.startswith('http'):

    im = Image.open(requests.get(imagepath, stream=True).raw)

    else:

    im = Image.open(imagepath)

    # Transform

    img = transform(im).unsqueeze(0)

    # Inference

    with torch.nograd():

    outputs = model(img)

    # Post-process

    probas = outputs['predlogits'].softmax(-1)[0, :, :-1]

    keep = probas.max(-1).values > threshold

    # Convert boxes from [0, 1] to image coordinates

    bboxesscaled = rescalebboxes(outputs['predboxes'][0, keep], im.size)

    return probas[keep], bboxesscaled, im

    def rescalebboxes(outbbox, size):

    """Convert normalized boxes to image coordinates."""

    imgw, imgh = size

    b = boxcxcywhtoxyxy(outbbox)

    b = b torch.tensor([imgw, imgh, imgw, imgh], dtype=torch.float32)

    return b

    def boxcxcywhtoxyxy(x):

    """Convert boxes from center format to corner format."""

    xc, yc, w, h = x.unbind(-1)

    b = [(xc - 0.5 w), (yc - 0.5 h),

    (xc + 0.5 w), (yc + 0.5 h)]

    return torch.stack(b, dim=-1)

    3. Visualisasi Hasil

    def plotresults(pilimg, prob, boxes):
    

    """Visualize detection results."""

    plt.figure(figsize=(16, 10))

    plt.imshow(pilimg)

    ax = plt.gca()

    colors = COLORS 100

    for p, (xmin, ymin, xmax, ymax), c in zip(prob, boxes.tolist(), colors):

    ax.addpatch(plt.Rectangle(

    (xmin, ymin), xmax - xmin, ymax - ymin,

    fill=False, color=c, linewidth=3

    ))

    cl = p.argmax()

    text = f'{CLASSES[cl]}: {p[cl]:0.2f}'

    ax.text(xmin, ymin, text, fontsize=15,

    bbox=dict(facecolor='yellow', alpha=0.5))

    plt.axis('off')

    plt.tightlayout()

    plt.savefig('detectionresult.png', dpi=150, bboxinches='tight')

    plt.show()

    Run detection

    url = 'http://images.cocodataset.org/val2017/000000039769.jpg'

    probas, bboxes, image = detect(url, model, transform)

    plotresults(image, probas, bboxes)

    print(f"Detected {len(probas)} objects")

    for p, box in zip(probas, bboxes):

    cl = p.argmax()

    print(f" {CLASSES[cl]}: {p[cl]:.2f} at {box.tolist()}")

    Pretrained Models

    Model yang Tersedia

    | Model | Backbone | Box AP | URL |

    |-------|----------|--------|-----|

    | DETR | ResNet-50 | 42.0 | detrresnet50 |

    | DETR-DC5 | ResNet-50 | 43.3 | detrresnet50dc5 |

    | DETR | ResNet-101 | 43.5 | detrresnet101 |

    | DETR-DC5 | ResNet-101 | 44.9 | detrresnet101dc5 |

    Load Different Models

    # ResNet-50 backbone
    

    modelr50 = torch.hub.load('facebookresearch/detr:main', 'detrresnet50', pretrained=True)

    ResNet-50 with dilated C5 stage

    modelr50dc5 = torch.hub.load('facebookresearch/detr:main', 'detrresnet50dc5', pretrained=True)

    ResNet-101 backbone

    modelr101 = torch.hub.load('facebookresearch/detr:main', 'detrresnet101', pretrained=True)

    ResNet-101 with dilated C5 stage

    modelr101dc5 = torch.hub.load('facebookresearch/detr:main', 'detrresnet101dc5', pretrained=True)

    Load dari Checkpoint

    # Download checkpoint
    

    import urllib.request

    checkpointurl = 'https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth'

    urllib.request.urlretrieve(checkpointurl, 'detr-r50.pth')

    Load checkpoint

    checkpoint = torch.load('detr-r50.pth', maplocation='cpu')

    model.loadstatedict(checkpoint['model'])

    Training DETR

    1. Persiapan Dataset COCO

    # Download COCO 2017
    

    mkdir -p data/coco

    cd data/coco

    Download images

    wget http://images.cocodataset.org/zips/train2017.zip

    wget http://images.cocodataset.org/zips/val2017.zip

    Download annotations

    wget http://images.cocodataset.org/annotations/annotationstrainval2017.zip

    Extract

    unzip train2017.zip

    unzip val2017.zip

    unzip annotationstrainval2017.zip

    Struktur folder:

    data/
    

    └── coco/

    ├── train2017/

    ├── val2017/

    └── annotations/

    ├── instancestrain2017.json

    └── instancesval2017.json

    2. Training Command

    # Single GPU training
    

    python main.py --cocopath /path/to/coco

    Multi-GPU training (8 GPUs)

    python -m torch.distributed.launch \

    --nprocpernode=8 \

    --useenv main.py \

    --cocopath /path/to/coco

    Training dengan custom settings

    python main.py \

    --cocopath /path/to/coco \

    --batchsize 2 \

    --epochs 300 \

    --lr 1e-4 \

    --lrbackbone 1e-5 \

    --numqueries 100 \

    --outputdir outputs/detrcustom

    3. Training Configuration

    # Default hyperparameters (dari paper)
    

    args = {

    # Optimizer

    'lr': 1e-4, # Learning rate untuk transformer

    'lrbackbone': 1e-5, # Learning rate untuk backbone

    'weightdecay': 1e-4, # Weight decay

    # Architecture

    'backbone': 'resnet50', # Backbone CNN

    'numqueries': 100, # Jumlah object queries

    'hiddendim': 256, # Hidden dimension transformer

    'nheads': 8, # Attention heads

    'enclayers': 6, # Encoder layers

    'declayers': 6, # Decoder layers

    'dimfeedforward': 2048, # FFN dimension

    'dropout': 0.1, # Dropout rate

    # Training

    'epochs': 300, # Total epochs

    'batchsize': 2, # Batch size per GPU

    'clipmaxnorm': 0.1, # Gradient clipping

    # Loss weights

    'setcostclass': 1, # Class cost untuk Hungarian matching

    'setcostbbox': 5, # L1 box cost

    'setcostgiou': 2, # GIoU cost

    'bboxlosscoef': 5, # Box L1 loss coefficient

    'gioulosscoef': 2, # GIoU loss coefficient

    'eoscoef': 0.1, # "No object" class weight

    }

    4. Custom Training Script

    import torch
    

    from torch.utils.data import DataLoader

    from detr.models import buildmodel

    from detr.datasets import builddataset

    from detr.engine import trainoneepoch, evaluate

    def traindetr(args):

    # Build model

    model, criterion, postprocessors = buildmodel(args)

    model.to(args.device)

    # Build dataset

    datasettrain = builddataset(imageset='train', args=args)

    datasetval = builddataset(imageset='val', args=args)

    # DataLoaders

    samplertrain = torch.utils.data.RandomSampler(datasettrain)

    samplerval = torch.utils.data.SequentialSampler(datasetval)

    dataloadertrain = DataLoader(

    datasettrain,

    batchsize=args.batchsize,

    sampler=samplertrain,

    collatefn=utils.collatefn,

    numworkers=args.numworkers

    )

    dataloaderval = DataLoader(

    datasetval,

    batchsize=args.batchsize,

    sampler=samplerval,

    collatefn=utils.collatefn,

    numworkers=args.numworkers

    )

    # Optimizer

    paramdicts = [

    {"params": [p for n, p in model.namedparameters()

    if "backbone" not in n and p.requiresgrad]},

    {"params": [p for n, p in model.namedparameters()

    if "backbone" in n and p.requiresgrad],

    "lr": args.lrbackbone},

    ]

    optimizer = torch.optim.AdamW(paramdicts, lr=args.lr, weightdecay=args.weightdecay)

    # LR Scheduler

    lrscheduler = torch.optim.lrscheduler.StepLR(optimizer, args.lrdrop)

    # Training loop

    for epoch in range(args.epochs):

    trainstats = trainoneepoch(

    model, criterion, dataloadertrain,

    optimizer, args.device, epoch, args.clipmaxnorm

    )

    lrscheduler.step()

    # Evaluate

    teststats, cocoevaluator = evaluate(

    model, criterion, postprocessors,

    dataloaderval, args.device

    )

    # Save checkpoint

    if (epoch + 1) % 10 == 0:

    torch.save({

    'model': model.statedict(),

    'optimizer': optimizer.statedict(),

    'lrscheduler': lrscheduler.statedict(),

    'epoch': epoch,

    }, f'checkpoint{epoch:04d}.pth')

    Evaluation

    1. Evaluate Pretrained Model

    python main.py \
    

    --batchsize 2 \

    --noauxloss \

    --eval \

    --resume https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth \

    --cocopath /path/to/coco

    2. Evaluation Script

    from detr.datasets.cocoeval import CocoEvaluator
    

    from detr.datasets.coco import makecocotransforms

    def evaluatemodel(model, dataloader, device):

    model.eval()

    cocoevaluator = CocoEvaluator(dataloader.dataset.coco, ['bbox'])

    for samples, targets in dataloader:

    samples = samples.to(device)

    targets = [{k: v.to(device) for k, v in t.items()} for t in targets]

    with torch.nograd():

    outputs = model(samples)

    # Post-process

    origtargetsizes = torch.stack([t["origsize"] for t in targets], dim=0)

    results = postprocessors'bbox'

    res = {target['imageid'].item(): output

    for target, output in zip(targets, results)}

    cocoevaluator.update(res)

    cocoevaluator.synchronizebetweenprocesses()

    cocoevaluator.accumulate()

    cocoevaluator.summarize()

    return cocoevaluator

    Run evaluation

    stats = evaluatemodel(model, dataloaderval, device)

    print(f"AP: {stats.cocoeval['bbox'].stats[0]:.3f}")

    print(f"AP50: {stats.cocoeval['bbox'].stats[1]:.3f}")

    print(f"AP75: {stats.cocoeval['bbox'].stats[2]:.3f}")

    Fine-tuning pada Custom Dataset

    1. Persiapan Dataset Custom

    import json
    

    from PIL import Image

    from torch.utils.data import Dataset

    class CustomCocoDataset(Dataset):

    """

    Custom dataset dalam format COCO.

    """

    def init(self, imgfolder, annfile, transforms=None):

    self.imgfolder = imgfolder

    self.transforms = transforms

    with open(annfile, 'r') as f:

    self.coco = json.load(f)

    self.ids = [img['id'] for img in self.coco['images']]

    # Build image id to annotations mapping

    self.imgtoanns = {}

    for ann in self.coco['annotations']:

    imgid = ann['imageid']

    if imgid not in self.imgtoanns:

    self.imgtoanns[imgid] = []

    self.imgtoanns[imgid].append(ann)

    def len(self):

    return len(self.ids)

    def getitem(self, idx):

    imgid = self.ids[idx]

    # Get image info

    imginfo = next(img for img in self.coco['images'] if img['id'] == imgid)

    imgpath = f"{self.imgfolder}/{imginfo['filename']}"

    img = Image.open(imgpath).convert('RGB')

    # Get annotations

    anns = self.imgtoanns.get(imgid, [])

    # Prepare target

    boxes = []

    labels = []

    for ann in anns:

    x, y, w, h = ann['bbox']

    boxes.append([x, y, x + w, y + h])

    labels.append(ann['categoryid'])

    target = {

    'boxes': torch.tensor(boxes, dtype=torch.float32),

    'labels': torch.tensor(labels, dtype=torch.int64),

    'imageid': torch.tensor([imgid]),

    'origsize': torch.tensor([img.height, img.width]),

    'size': torch.tensor([img.height, img.width]),

    }

    if self.transforms:

    img, target = self.transforms(img, target)

    return img, target

    2. Format Annotation COCO

    {
    

    "images": [

    {"id": 1, "filename": "image1.jpg", "width": 640, "height": 480},

    {"id": 2, "filename": "image2.jpg", "width": 800, "height": 600}

    ],

    "annotations": [

    {"id": 1, "imageid": 1, "categoryid": 1, "bbox": [100, 100, 200, 150]},

    {"id": 2, "imageid": 1, "categoryid": 2, "bbox": [300, 200, 100, 100]},

    {"id": 3, "imageid": 2, "categoryid": 1, "bbox": [50, 50, 300, 200]}

    ],

    "categories": [

    {"id": 1, "name": "cat"},

    {"id": 2, "name": "dog"}

    ]

    }

    3. Modify Model untuk Custom Classes

    def buildcustomdetr(numclasses):
    

    """

    Build DETR untuk custom number of classes.

    """

    # Load pretrained model

    model = torch.hub.load('facebookresearch/detr:main', 'detrresnet50', pretrained=True)

    # Modify class prediction head

    # Original: 91 COCO classes + 1 "no object" = 92

    # Custom: numclasses + 1 "no object"

    model.classembed = torch.nn.Linear(

    model.classembed.infeatures,

    numclasses + 1

    )

    # Reinitialize the new layer

    torch.nn.init.normal(model.classembed.weight, std=0.01)

    torch.nn.init.constant(model.classembed.bias, 0)

    # Set "no object" bias to higher value (makes model predict "no object" more often initially)

    model.classembed.bias.data[-1] = -2.0

    return model

    Example: 5 custom classes

    numclasses = 5

    model = buildcustomdetr(numclasses)

    print(f"Model output classes: {model.classembed.outfeatures}")

    4. Fine-tuning Script

    def finetunedetr(model, trainloader, valloader, numepochs=50):
    

    """

    Fine-tune DETR on custom dataset.

    """

    device = torch.device('cuda' if torch.cuda.isavailable() else 'cpu')

    model.to(device)

    # Freeze backbone for first few epochs

    for param in model.backbone.parameters():

    param.requiresgrad = False

    # Optimizer

    optimizer = torch.optim.AdamW([

    {'params': model.transformer.parameters(), 'lr': 1e-4},

    {'params': model.classembed.parameters(), 'lr': 1e-3},

    {'params': model.bboxembed.parameters(), 'lr': 1e-4},

    {'params': model.queryembed.parameters(), 'lr': 1e-4},

    ], weightdecay=1e-4)

    # Training loop

    for epoch in range(numepochs):

    model.train()

    totalloss = 0

    for batchidx, (images, targets) in enumerate(trainloader):

    images = images.to(device)

    targets = [{k: v.to(device) for k, v in t.items()} for t in targets]

    outputs = model(images)

    lossdict = criterion(outputs, targets)

    loss = sum(lossdict.values())

    optimizer.zerograd()

    loss.backward()

    torch.nn.utils.clipgradnorm(model.parameters(), 0.1)

    optimizer.step()

    totalloss += loss.item()

    # Unfreeze backbone after epoch 10

    if epoch == 10:

    for param in model.backbone.parameters():

    param.requiresgrad = True

    optimizer.addparamgroup({

    'params': model.backbone.parameters(),

    'lr': 1e-5

    })

    print(f"Epoch {epoch+1}/{numepochs}, Loss: {totalloss/len(trainloader):.4f}")

    return model

    Panoptic Segmentation

    1. Load Panoptic Model

    # Load DETR with panoptic head
    

    model = torch.hub.load(

    'facebookresearch/detr:main',

    'detrresnet50panoptic',

    pretrained=True,

    returnpostprocessor=True,

    numclasses=250 # COCO panoptic classes

    )

    detr, postprocessor = model

    detr.eval()

    2. Panoptic Inference

    def panopticinference(imagepath, model, postprocessor):
    

    """

    Run panoptic segmentation.

    """

    im = Image.open(imagepath)

    # Transform

    transform = T.Compose([

    T.Resize(800),

    T.ToTensor(),

    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

    ])

    img = transform(im).unsqueeze(0)

    with torch.nograd():

    outputs = model(img)

    # Post-process

    result = postprocessor(outputs, torch.tensor([[im.height, im.width]]))[0]

    # result contains:

    # - 'segmentation': Segmentation mask (H, W) dengan segment IDs

    # - 'segmentsinfo': List of dicts dengan info tiap segment

    return result

    Example

    result = panopticinference('image.jpg', detr, postprocessor)

    print(f"Number of segments: {len(result['segmentsinfo'])}")

    for seg in result['segmentsinfo']:

    print(f" ID: {seg['id']}, Category: {seg['categoryid']}, "

    f"Is Thing: {seg['isthing']}")

    3. Visualisasi Panoptic

    import numpy as np
    

    from panopticapi.utils import rgb2id

    def visualizepanoptic(image, result):

    """

    Visualize panoptic segmentation result.

    """

    # Get segmentation mask

    segmask = result['segmentation'].numpy()

    # Create color map

    np.random.seed(42)

    colors = np.random.randint(0, 255, (256, 3), dtype=np.uint8)

    # Apply colors

    coloredmask = colors[segmask % 256]

    # Blend with original image

    imagenp = np.array(image)

    blended = (0.5 imagenp + 0.5 coloredmask).astype(np.uint8)

    plt.figure(figsize=(16, 8))

    plt.subplot(1, 3, 1)

    plt.imshow(image)

    plt.title('Original')

    plt.axis('off')

    plt.subplot(1, 3, 2)

    plt.imshow(coloredmask)

    plt.title('Segmentation')

    plt.axis('off')

    plt.subplot(1, 3, 3)

    plt.imshow(blended)

    plt.title('Blended')

    plt.axis('off')

    plt.tightlayout()

    plt.savefig('panopticresult.png')

    plt.show()

    Best Practices

    1. Memory Optimization

    # Gradient checkpointing untuk mengurangi memory
    

    from torch.utils.checkpoint import checkpoint

    Mixed precision training

    from torch.cuda.amp import autocast, GradScaler

    scaler = GradScaler()

    for images, targets in trainloader:

    with autocast():

    outputs = model(images)

    loss = criterion(outputs, targets)

    scaler.scale(loss).backward()

    scaler.step(optimizer)

    scaler.update()

    2. Data Augmentation

    import albumentations as A
    

    from albumentations.pytorch import ToTensorV2

    traintransform = A.Compose([

    A.RandomResizedCrop(800, 800, scale=(0.5, 1.0)),

    A.HorizontalFlip(p=0.5),

    A.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),

    A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),

    ToTensorV2(),

    ], bboxparams=A.BboxParams(format='coco', labelfields=['labels']))

    3. Inference Optimization

    # TorchScript untuk faster inference
    

    scriptedmodel = torch.jit.script(model)

    scriptedmodel.save('detrscripted.pt')

    ONNX export

    torch.onnx.export(

    model,

    dummyinput,

    'detr.onnx',

    inputnames=['image'],

    outputnames=['predlogits', 'predboxes'],

    dynamicaxes={'image': {0: 'batch', 2: 'height', 3: 'width'}}

    )

    4. Batch Inference

    def batchinference(imagepaths, model, transform, batchsize=8):
    

    """

    Efficient batch inference.

    """

    allresults = []

    for i in range(0, len(imagepaths), batchsize):

    batchpaths = imagepaths[i:i+batchsize]

    # Load and transform images

    images = []

    sizes = []

    for path in batchpaths:

    img = Image.open(path)

    sizes.append(img.size)

    images.append(transform(img))

    # Stack into batch

    batch = torch.stack(images)

    with torch.nograd():

    outputs = model(batch.to(device))

    # Process each image in batch

    for j, (prob, boxes) in enumerate(zip(

    outputs['predlogits'].softmax(-1),

    outputs['predboxes']

    )):

    # Filter by threshold

    keep = prob[:, :-1].max(-1).values > 0.7

    allresults.append({

    'path': batchpaths[j],

    'scores': prob[keep],

    'boxes': rescalebboxes(boxes[keep], sizes[j])

    })

    return allresults

    Troubleshooting

    1. Out of Memory

    # Reduce batch size
    

    args.batchsize = 1

    Use gradient accumulation

    accumulationsteps = 4

    for i, (images, targets) in enumerate(trainloader):

    loss = criterion(model(images), targets)

    loss = loss / accumulationsteps

    loss.backward()

    if (i + 1) % accumulationsteps == 0:

    optimizer.step()

    optimizer.zerograd()

    2. Training Tidak Converge

    # Cek learning rate
    

    LR terlalu tinggi dapat menyebabkan divergence

    args.lr = 1e-5 # Mulai dengan LR lebih kecil

    Pastikan data augmentation tidak terlalu agresif

    Pastikan normalization benar

    3. Low AP pada Custom Dataset

    # Pastikan format annotation benar
    

    Cek class balance

    Pertimbangkan lebih banyak epochs

    Fine-tune dari pretrained model

    Kesimpulan

    DETR adalah pendekatan inovatif untuk object detection:

    Key Takeaways:

  • End-to-End: Tidak perlu NMS atau anchor boxes
  • Transformer-based: Global reasoning untuk deteksi objek
  • Simple: Arsitektur yang elegan dan mudah dipahami
  • Versatile: Mendukung detection dan segmentation
  • State-of-the-art: Competitive dengan metode tradisional
  • Kapan Menggunakan DETR:

    Use DETR when:
    • Butuh end-to-end object detection
    • Dataset memiliki objek dengan relasi kompleks
    • Ingin menghindari hand-crafted components
    • Memerlukan panoptic segmentation
    • Research atau prototyping

    Consider alternatives when:
    • Real-time inference diperlukan (DETR lebih lambat dari YOLO)
    • Dataset sangat kecil (DETR butuh banyak data)
    • Resource terbatas (DETR memory-intensive)

    Resources:

    • Paper: "End-to-End Object Detection with Transformers"
    • GitHub: https://github.com/facebookresearch/detr
    • Colab Notebooks tersedia di repository

    Selamat menggunakan DETR!

    Artikel Terkait

    Florence-2: Model Vision Multi-Task dari Microsoft

    Florence-2: Model Vision Multi-Task dari Microsoft Daftar Isi Pendahuluan Prasyarat Instalasi Memuat Model Florence-2

    Supervision: Toolkit Computer Vision dari Roboflow

    Supervision: Toolkit Computer Vision dari Roboflow Dalam proyek computer vision, setelah model mendeteksi objek, Anda ma...

    Tutorial Lengkap Ultralytics: Object Detection dengan YOLO

    Tutorial Lengkap Ultralytics: Object Detection dengan YOLO Ultralytics adalah framework Python yang menyediakan implemen...

    Tutorial Surya OCR: Document AI untuk Text Detection, OCR, dan Layout Analysis

    Tutorial Surya OCR: Document AI untuk Text Detection, OCR, dan Layout Analysis Surya adalah library Document AI open-sou...