OpenCV + Deep Learning Tutorial: Modern Image Processing with Python

# OpenCV + Deep Learning: Tutorial Komprehensif ## Daftar Isi 1. [Pendahuluan](#pendahuluan) 2. [Prasyarat](#prasyarat) 3. [Dasar-Dasar Preprocessing Gambar](#dasar-dasar-preprocessing-gambar) 4. [T...

By Ruby Abdullah · · tutorial
OpenCVDeep LearningComputer VisionImage ProcessingPythonDNN

OpenCV + Deep Learning: A Comprehensive Tutorial

Table of Contents

  • Introduction
  • Prerequisites
  • Image Preprocessing Fundamentals
  • Data Augmentation Techniques
  • Using the DNN Module for Inference
  • Face Detection with OpenCV DNN
  • Object Detection with Pre-trained Models
  • Video Processing Pipeline
  • Integration with PyTorch and TensorFlow
  • Best Practices
  • Conclusion

  • Introduction

    OpenCV (Open Source Computer Vision Library) is one of the most widely used libraries for computer vision tasks. When combined with deep learning frameworks, it becomes a powerful toolkit for building production-grade vision applications. This tutorial covers the essential techniques for leveraging OpenCV alongside deep learning models, from basic image preprocessing to deploying inference pipelines with pre-trained neural networks.

    Whether you are building a real-time face detection system, an object detection pipeline, or integrating vision models into a larger application, understanding how OpenCV interfaces with deep learning is a critical skill.


    Prerequisites

    Before starting, ensure you have the following installed:

    # Install required packages
    

    pip install opencv-python opencv-contrib-python numpy

    pip install torch torchvision

    pip install tensorflow

    pip install albumentations

    System requirements:
    • Python 3.8 or higher
    • A machine with at least 8 GB RAM (GPU recommended for training)
    • Basic understanding of Python, NumPy, and neural network concepts

    Verify your installation:

    import cv2
    

    import numpy as np

    import torch

    import tensorflow as tf

    print(f"OpenCV version: {cv2.version}")

    print(f"NumPy version: {np.version}")

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

    print(f"TensorFlow version: {tf.version}")


    Image Preprocessing Fundamentals

    Image preprocessing is the foundation of any computer vision pipeline. Proper preprocessing ensures that your deep learning model receives clean, normalized input data.

    Reading and Color Space Conversion

    import cv2
    

    import numpy as np

    Read an image (BGR format by default)

    image = cv2.imread("input.jpg")

    Convert color spaces

    rgbimage = cv2.cvtColor(image, cv2.COLORBGR2RGB)

    grayimage = cv2.cvtColor(image, cv2.COLORBGR2GRAY)

    hsvimage = cv2.cvtColor(image, cv2.COLORBGR2HSV)

    labimage = cv2.cvtColor(image, cv2.COLORBGR2LAB)

    Resizing and Normalization

    def preprocessformodel(image, targetsize=(224, 224)):
    

    """

    Standard preprocessing pipeline for deep learning models.

    """

    # Resize while maintaining aspect ratio with padding

    h, w = image.shape[:2]

    scale = min(targetsize[0] / h, targetsize[1] / w)

    newh, neww = int(h scale), int(w scale)

    resized = cv2.resize(image, (neww, newh), interpolation=cv2.INTERLINEAR)

    # Create canvas and center the image

    canvas = np.zeros((targetsize[0], targetsize[1], 3), dtype=np.uint8)

    yoffset = (targetsize[0] - newh) // 2

    xoffset = (targetsize[1] - neww) // 2

    canvas[yoffset:yoffset + newh, xoffset:xoffset + neww] = resized

    # Normalize to [0, 1] range

    normalized = canvas.astype(np.float32) / 255.0

    # Apply ImageNet mean and std normalization

    mean = np.array([0.485, 0.456, 0.406])

    std = np.array([0.229, 0.224, 0.225])

    normalized = (normalized - mean) / std

    return normalized

    Histogram Equalization and CLAHE

    def enhancecontrast(image):
    

    """Apply CLAHE for adaptive contrast enhancement."""

    lab = cv2.cvtColor(image, cv2.COLORBGR2LAB)

    lchannel, achannel, bchannel = cv2.split(lab)

    # Apply CLAHE to the L channel

    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))

    enhancedl = clahe.apply(lchannel)

    merged = cv2.merge([enhancedl, achannel, bchannel])

    result = cv2.cvtColor(merged, cv2.COLORLAB2BGR)

    return result


    Data Augmentation Techniques

    Data augmentation artificially expands your training dataset by applying random transformations to images.

    OpenCV-based Augmentation

    import random
    
    

    def augmentimage(image):

    """Apply a random set of augmentations using OpenCV."""

    augmented = image.copy()

    # Random horizontal flip

    if random.random() > 0.5:

    augmented = cv2.flip(augmented, 1)

    # Random rotation (-15 to 15 degrees)

    angle = random.uniform(-15, 15)

    h, w = augmented.shape[:2]

    matrix = cv2.getRotationMatrix2D((w / 2, h / 2), angle, 1.0)

    augmented = cv2.warpAffine(augmented, matrix, (w, h))

    # Random brightness adjustment

    brightness = random.randint(-30, 30)

    augmented = np.clip(augmented.astype(np.int16) + brightness, 0, 255).astype(np.uint8)

    # Random Gaussian blur

    if random.random() > 0.5:

    ksize = random.choice([3, 5, 7])

    augmented = cv2.GaussianBlur(augmented, (ksize, ksize), 0)

    # Random crop and resize

    if random.random() > 0.5:

    croppct = random.uniform(0.8, 1.0)

    croph, cropw = int(h croppct), int(w croppct)

    ystart = random.randint(0, h - croph)

    xstart = random.randint(0, w - cropw)

    augmented = augmented[ystart:ystart + croph, xstart:xstart + cropw]

    augmented = cv2.resize(augmented, (w, h))

    return augmented

    Using Albumentations for Advanced Augmentation

    import albumentations as A
    
    

    transform = A.Compose([

    A.RandomResizedCrop(height=224, width=224, scale=(0.8, 1.0)),

    A.HorizontalFlip(p=0.5),

    A.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1, p=0.5),

    A.GaussNoise(varlimit=(10, 50), p=0.3),

    A.GaussianBlur(blurlimit=(3, 7), p=0.3),

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

    ])

    Apply augmentation

    augmented = transform(image=image)["image"]


    Using the DNN Module for Inference

    OpenCV's dnn module allows you to load and run pre-trained models from multiple frameworks without requiring the original framework at runtime.

    Loading Models from Different Frameworks

    # Load a Caffe model
    

    netcaffe = cv2.dnn.readNetFromCaffe("deploy.prototxt", "model.caffemodel")

    Load a TensorFlow model

    nettf = cv2.dnn.readNetFromTensorflow("frozengraph.pb", "graph.pbtxt")

    Load an ONNX model (universal format)

    netonnx = cv2.dnn.readNetFromONNX("model.onnx")

    Load a Darknet (YOLO) model

    netdarknet = cv2.dnn.readNetFromDarknet("yolov3.cfg", "yolov3.weights")

    Running Inference with the DNN Module

    def rundnninference(net, image, inputsize=(300, 300)):
    

    """Run inference using OpenCV DNN module."""

    # Create a blob from the image

    blob = cv2.dnn.blobFromImage(

    image,

    scalefactor=1.0 / 255.0,

    size=inputsize,

    mean=(0, 0, 0),

    swapRB=True,

    crop=False

    )

    # Set the input

    net.setInput(blob)

    # Set the backend and target for acceleration

    net.setPreferableBackend(cv2.dnn.DNNBACKENDOPENCV)

    net.setPreferableTarget(cv2.dnn.DNNTARGETCPU)

    # For GPU: cv2.dnn.DNNTARGETCUDA

    # Forward pass

    output = net.forward()

    return output


    Face Detection with OpenCV DNN

    OpenCV provides a deep learning-based face detector that is far more accurate than the traditional Haar Cascade approach.

    def detectfacesdnn(image, confidencethreshold=0.5):
    

    """

    Detect faces using OpenCV's DNN-based face detector.

    Uses a pre-trained SSD model with a ResNet-10 backbone.

    """

    # Load the pre-trained model

    prototxt = "deploy.prototxt"

    modelpath = "res10300x300ssditer140000.caffemodel"

    net = cv2.dnn.readNetFromCaffe(prototxt, modelpath)

    h, w = image.shape[:2]

    # Prepare the blob

    blob = cv2.dnn.blobFromImage(

    cv2.resize(image, (300, 300)),

    scalefactor=1.0,

    size=(300, 300),

    mean=(104.0, 177.0, 123.0)

    )

    net.setInput(blob)

    detections = net.forward()

    faces = []

    for i in range(detections.shape[2]):

    confidence = detections[0, 0, i, 2]

    if confidence > confidencethreshold:

    box = detections[0, 0, i, 3:7] np.array([w, h, w, h])

    x1, y1, x2, y2 = box.astype("int")

    faces.append({

    "box": (x1, y1, x2, y2),

    "confidence": float(confidence)

    })

    # Draw the bounding box

    cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)

    label = f"Face: {confidence:.2f}"

    cv2.putText(image, label, (x1, y1 - 10),

    cv2.FONTHERSHEYSIMPLEX, 0.5, (0, 255, 0), 2)

    return image, faces


    Object Detection with Pre-trained Models

    YOLOv4 Object Detection

    class YOLODetector:
    

    """Object detection using YOLOv4 with OpenCV DNN."""

    def init(self, configpath, weightspath, namespath):

    self.net = cv2.dnn.readNetFromDarknet(configpath, weightspath)

    self.net.setPreferableBackend(cv2.dnn.DNNBACKENDOPENCV)

    self.net.setPreferableTarget(cv2.dnn.DNNTARGETCPU)

    with open(namespath, "r") as f:

    self.classes = [line.strip() for line in f.readlines()]

    layernames = self.net.getLayerNames()

    self.outputlayers = [

    layernames[i - 1] for i in self.net.getUnconnectedOutLayers()

    ]

    def detect(self, image, confthreshold=0.5, nmsthreshold=0.4):

    """Run object detection on a single image."""

    h, w = image.shape[:2]

    blob = cv2.dnn.blobFromImage(

    image, 1 / 255.0, (416, 416), swapRB=True, crop=False

    )

    self.net.setInput(blob)

    outputs = self.net.forward(self.outputlayers)

    boxes, confidences, classids = [], [], []

    for output in outputs:

    for detection in output:

    scores = detection[5:]

    classid = np.argmax(scores)

    confidence = scores[classid]

    if confidence > confthreshold:

    centerx = int(detection[0] w)

    centery = int(detection[1] h)

    detw = int(detection[2] w)

    deth = int(detection[3] h)

    x = int(centerx - detw / 2)

    y = int(centery - deth / 2)

    boxes.append([x, y, detw, deth])

    confidences.append(float(confidence))

    classids.append(classid)

    # Apply Non-Maximum Suppression

    indices = cv2.dnn.NMSBoxes(boxes, confidences, confthreshold, nmsthreshold)

    results = []

    for i in indices.flatten():

    x, y, bw, bh = boxes[i]

    results.append({

    "class": self.classes[classids[i]],

    "confidence": confidences[i],

    "box": (x, y, x + bw, y + bh)

    })

    # Draw results

    color = (0, 255, 0)

    cv2.rectangle(image, (x, y), (x + bw, y + bh), color, 2)

    label = f"{self.classes[classids[i]]}: {confidences[i]:.2f}"

    cv2.putText(image, label, (x, y - 5),

    cv2.FONTHERSHEYSIMPLEX, 0.5, color, 2)

    return image, results

    Usage

    detector = YOLODetector("yolov4.cfg", "yolov4.weights", "coco.names")

    resultimage, detections = detector.detect(cv2.imread("test.jpg"))


    Video Processing Pipeline

    Real-time Object Detection on Video

    class VideoProcessor:
    

    """Process video streams with deep learning models."""

    def init(self, detector):

    self.detector = detector

    def processvideo(self, source=0, outputpath=None):

    """

    Process video from camera or file.

    source: 0 for webcam, or path to video file.

    """

    cap = cv2.VideoCapture(source)

    if not cap.isOpened():

    raise ValueError(f"Cannot open video source: {source}")

    fps = cap.get(cv2.CAPPROPFPS) or 30

    width = int(cap.get(cv2.CAPPROPFRAMEWIDTH))

    height = int(cap.get(cv2.CAPPROPFRAMEHEIGHT))

    writer = None

    if outputpath:

    fourcc = cv2.VideoWriterfourcc("mp4v")

    writer = cv2.VideoWriter(outputpath, fourcc, fps, (width, height))

    framecount = 0

    while True:

    ret, frame = cap.read()

    if not ret:

    break

    framecount += 1

    # Process every nth frame for performance

    if framecount % 2 == 0:

    processed, detections = self.detector.detect(frame)

    else:

    processed = frame

    # Display FPS

    cv2.putText(processed, f"Frame: {framecount}",

    (10, 30), cv2.FONTHERSHEYSIMPLEX, 1, (0, 0, 255), 2)

    if writer:

    writer.write(processed)

    cv2.imshow("Detection", processed)

    if cv2.waitKey(1) & 0xFF == ord("q"):

    break

    cap.release()

    if writer:

    writer.release()

    cv2.destroyAllWindows()

    Usage

    processor = VideoProcessor(detector)

    processor.processvideo(source="inputvideo.mp4", outputpath="output.mp4")


    Integration with PyTorch and TensorFlow

    OpenCV to PyTorch Pipeline

    import torch
    

    import torchvision.transforms as T

    from torchvision import models

    def opencvtopytorchinference(imagepath, modelname="resnet50"):

    """Run inference using a PyTorch model with OpenCV preprocessing."""

    # Read with OpenCV

    image = cv2.imread(imagepath)

    imagergb = cv2.cvtColor(image, cv2.COLORBGR2RGB)

    # Convert to PyTorch tensor

    transform = T.Compose([

    T.ToPILImage(),

    T.Resize(256),

    T.CenterCrop(224),

    T.ToTensor(),

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

    ])

    inputtensor = transform(imagergb).unsqueeze(0)

    # Load model and run inference

    model = models.resnet50(pretrained=True)

    model.eval()

    with torch.nograd():

    output = model(inputtensor)

    probabilities = torch.softmax(output[0], dim=0)

    top5prob, top5idx = torch.topk(probabilities, 5)

    return list(zip(top5idx.tolist(), top5prob.tolist()))

    OpenCV to TensorFlow Pipeline

    import tensorflow as tf
    
    

    def opencvtotensorflowinference(imagepath):

    """Run inference using a TensorFlow model with OpenCV preprocessing."""

    # Read with OpenCV

    image = cv2.imread(imagepath)

    imagergb = cv2.cvtColor(image, cv2.COLORBGR2RGB)

    # Preprocess for TensorFlow

    imageresized = cv2.resize(imagergb, (224, 224))

    imagenormalized = imageresized.astype(np.float32) / 255.0

    inputtensor = np.expanddims(imagenormalized, axis=0)

    # Load a pre-trained MobileNetV2

    model = tf.keras.applications.MobileNetV2(weights="imagenet")

    predictions = model.predict(

    tf.keras.applications.mobilenetv2.preprocessinput(

    np.expanddims(cv2.resize(imagergb, (224, 224)), axis=0)

    )

    )

    decoded = tf.keras.applications.mobilenetv2.decodepredictions(predictions, top=5)

    return decoded[0]

    Exporting PyTorch Models to ONNX for OpenCV

    def exporttoonnx(model, dummyinput, outputpath="model.onnx"):
    

    """Export a PyTorch model to ONNX format for OpenCV DNN."""

    model.eval()

    torch.onnx.export(

    model,

    dummyinput,

    outputpath,

    exportparams=True,

    opsetversion=11,

    doconstantfolding=True,

    inputnames=["input"],

    outputnames=["output"],

    dynamicaxes={"input": {0: "batchsize"}, "output": {0: "batchsize"}}

    )

    print(f"Model exported to {outputpath}")

    # Load back with OpenCV

    net = cv2.dnn.readNetFromONNX(outputpath)

    return net


    Best Practices

  • Always convert color spaces explicitly. OpenCV reads images in BGR, while most deep learning models expect RGB. Forgetting this conversion is one of the most common bugs.
  • Use ONNX as a bridge format. When deploying models with OpenCV DNN, export to ONNX from PyTorch or TensorFlow for maximum compatibility and performance.
  • Apply Non-Maximum Suppression (NMS) to filter overlapping detections. This is essential for any object detection pipeline.
  • Process video frames selectively. For real-time applications, skip frames or resize to smaller dimensions to maintain acceptable frame rates.
  • Use cv2.dnn.blobFromImage correctly. Understand the parameters: scalefactor, size, mean, swapRB, and crop. Incorrect blob creation is a frequent source of poor model accuracy.
  • Batch preprocessing when possible. Use cv2.dnn.blobFromImages for batch inference to improve throughput.
  • Profile your pipeline. Use net.getPerfProfile() to measure DNN inference time and identify bottlenecks.
  • Prefer INTERLINEAR for upscaling and INTERAREA for downscaling to get the best image quality during resizing.

  • Conclusion

    OpenCV combined with deep learning provides a robust foundation for building computer vision applications. The DNN module offers framework-agnostic inference, while OpenCV's image processing functions handle the preprocessing and postprocessing pipeline efficiently. By mastering the techniques in this tutorial -- from image preprocessing and augmentation to model integration and real-time video processing -- you can build scalable, production-ready vision systems.

    For further learning, explore OpenCV's support for CUDA acceleration, the G-API module for pipeline optimization, and more advanced architectures like transformer-based vision models.

    Related Articles

    Complete Ultralytics Tutorial: Object Detection with YOLO

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

    Complete Guide to MediaPipe: Computer Vision Made Easy

    Panduan Lengkap MediaPipe: Computer Vision Made Easy MediaPipe adalah framework open-source dari Google untuk membangun ...

    Surya OCR Tutorial: Document AI for Text Detection, OCR, and Layout Analysis

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

    PyTorch Geometric Tutorial: Graph Neural Networks in PyTorch

    Memulai dengan PyTorch Geometric: Graph Neural Network di PyTorch Sebagian besar machine learning bekerja pada grid (gam...