MilleVisionNotes

This site focuses on practical examples of controlling Basler industrial cameras
using the pylon SDK and C#, based on real-world development experience.

タグ: OpenCV

  • Implementing Background Subtraction (Motion Detection) in WPF with Basler pylon SDK + OpenCV (C# / .NET 8)

    Implementing Background Subtraction (Motion Detection) in WPF with Basler pylon SDK + OpenCV (C# / .NET 8)

    Once your live view is working, a natural next step is highlighting only what moved. In this article, we implement a simple background subtraction pipeline to detect motion regions, draw bounding boxes, and display the results in a WPF Image.


    ✅ Environment

    Because this implementation converts between BitmapSource and Mat, install the NuGet package:

    • OpenCvSharp4.WpfExtensions
    Item Details
    Camera Basler acA2500-14gm
    SDK pylon Camera Software Suite
    Language / GUI C# / .NET 8 / WPF
    Libraries OpenCvSharp4 (OpenCvSharp4.Windows, OpenCvSharp4.WpfExtensions)

    Recommended camera settings (for stable subtraction): Set ExposureAuto=Off, GainAuto=Off, and keep illumination stable (reduce flicker).

    Prerequisites from earlier posts (reference):


    Implementation Overview

    We will follow this workflow:

    1. Capture a background frame (a frame with no motion)
    2. Preprocess with Gaussian blur
    3. Compute absolute difference (AbsDiff) → threshold (Threshold) → opening (MorphologyEx(Open))
    4. Extract contours (FindContours) → draw bounding rectangles
    5. Display the processed frame in WPF

    Adding opening after threshold helps remove small speckle noise.


    🧩 XAML (Minimal UI)

    Add one column for a “Set BG” button and sliders for tuning.

    BackgroundSubtraction_View


    🔧 Core Code (Background Subtraction Pipeline)

    This logic ideally belongs in the Model layer, but to keep diffs small from previous articles, it is implemented in the ViewModel.

    The author tested on a Mono8 camera. If you use a color camera, convert to grayscale as needed.

    The ViewModel implements IDisposable to ensure OpenCV Mat resources are released.


    Code-Behind

    Dispose the ViewModel when the window closes.


    Example Run

    1. Click Set BG to capture the background frame.

    BackgroundSubtraction_BG 2. Move an object in the scene → motion regions are detected and boxed. 3. Use sliders to tune sensitivity and minimum area.

    BackgroundSubtraction_Detect


    Tuning Tips

    • Retake background when illumination changes

    • Threshold: increase to suppress sensor noise; decrease to detect subtle motion

    • Morphology iterations: increase if edges are jagged; decrease if boxes “bloat”

    • Min area: simple filter to reduce false positives

    • Speed-ups:

      • Apply camera ROI to reduce the processed area
      • Cv2.Resize to process a smaller image (scale coordinates back)
      • Cache blurred background (as shown) to avoid blurring every frame

    Common Pitfalls

    Symptom Likely Cause Fix
    Nothing detected Threshold too high / changes too small Lower threshold or increase blur kernel
    Entire frame white Auto exposure/gain is fluctuating Set ExposureAuto/GainAuto=Off, stabilize lighting
    Too many speckles Sensor noise / tiny vibration Keep opening (MorphTypes.Open) and tune kernel
    UI freezes Processing too heavy Move processing to another Task, use ROI / resize
    Memory grows Mat.Dispose() missing Use using blocks (as shown) and cache carefully

    Summary

    • Background subtraction highlights only moving regions
    • Fixed exposure/gain + stable lighting improves reliability
    • Tune threshold, minimum area, and morphology to balance sensitivity vs noise
    • ROI and resizing are effective for performance
  • Displaying and Saving Basler Camera Images with OpenCV

    Displaying and Saving Basler Camera Images with OpenCV

    Displaying and Saving Basler Camera Images with OpenCV

    pylon SDK × OpenCvSharp / C#

    When working with Basler cameras, converting captured images into OpenCV’s Mat format gives you access to a wide range of image processing algorithms.

    In this article, we’ll take a GrabResult from the Basler pylon SDK, convert it to an OpenCV Mat, and then:

    • Display it in real time using Cv2.ImShow
    • Save it as an image file using Cv2.ImWrite

    ✅ Environment

    Item Value
    Camera Basler acA2500-14gm
    SDK Basler pylon Camera Software Suite
    Pixel Format Mono8 (8-bit grayscale)
    OpenCV Wrapper OpenCvSharp4.Windows (via NuGet)

    🎯 Goal: Convert GrabResultMat → Display & Save

    Conceptual flow:

    [GrabResult] → [byte[]] → [Mat] → [ImShow / ImWrite]
    

    🔧 Converting GrabResult to Mat

    We’ll use PixelDataConverter.Convert() to extract pixel data from IGrabResult into a byte[], and then wrap that buffer as an OpenCV Mat.

    A convenient way is to implement an extension method on IGrabResult:

    💡 Note: For color formats (e.g., BGR8, RGB8), you’ll need to adjust OutputPixelFormat and MatType (e.g., CV_8UC3) accordingly.


    🖼 Real-Time Display with Cv2.ImShow

    We now extend the BaslerCameraSample class (introduced in the previous article on event-driven capture) to display buffered images using OpenCV.

    Here, we assume that _bufferedImageQueue is a queue of (DateTime, IGrabResult) that the ImageGrabbed event handler enqueues into.

    Example Test: Live Display for 10 Seconds

    Running this test opens an OpenCV window named “Camera” that shows the live feed from your Basler camera.


    💾 Saving Mat with ImWrite

    To save a Mat to disk, use ImWrite(). The following example:

    1. Captures one frame using Snap()
    2. Converts it to Mat
    3. Saves the image
    4. Applies a simple threshold operation and saves again
    5. Also saves via BitmapSource for comparison

    ImShowTest

    This creates three files:

    1. SnapAndSaveMatTest_Bitmap.bmp — saved from BitmapSource
    2. SnapAndSaveMatTest_Mat.bmp — saved from OpenCV Mat
    3. SnapAndSaveMatTest_Mat_Thresholded.bmp — thresholded version

    Comparing (1) and (2) confirms that both pipelines produce the same image.

    BitmapSource Mat Mat(Binary)
    BitmapSource Mat Mat(Binary)

    📌 Tips & Common Pitfalls

    Point Notes
    Pixel format For color (BGR8, RGB8), use MatType.CV_8UC3 and correct channel order
    Nothing shows in ImShow You must call Cv2.WaitKey(); otherwise the window won’t update
    OpenCvSharp packages Install both OpenCvSharp4 and OpenCvSharp4.runtime.windows via NuGet
    Performance considerations Pinning buffers is fast, but for very high rates you may want to profile allocations

    ✅ Summary

    • You can convert Basler pylon GrabResult to an OpenCV Mat via PixelDataConverter and a byte[] buffer.
    • Cv2.ImShow enables simple live viewing; Cv2.ImWrite lets you save images directly from Mat.
    • Once in Mat form, you can apply the full power of OpenCV: filtering, edge detection, feature extraction, etc.

    Author: @MilleVision