Skip to content
This repository has been archived by the owner on Feb 22, 2024. It is now read-only.

Image Processing

Ian Auty edited this page Mar 3, 2020 · 11 revisions

Revisions

  • v0.6 (Current)
  • v0.5

Contents

  1. Sharpen
  2. Edge Detection
  3. Gaussian Blur
  4. Strip Bayer metadata
  5. Custom convolution

Most of the image processing techniques available currently in MMALSharp are based on Matrix Convolutions which can be found on Wikipedia.

Sharpen

public async Task TakePictureManual()
{                        
    MMALCamera cam = MMALCamera.Instance;

    using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/", "jpg"))
    using (var imgEncoder = new MMALImageEncoder())
    using (var nullSink = new MMALNullSinkComponent())
    {
        cam.ConfigureCameraSettings();
        
        var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.RGB24, 90);

        // Create our component pipeline.         
        imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
                
        cam.Camera.StillPort.ConnectTo(imgEncoder);                    
        cam.Camera.PreviewPort.ConnectTo(nullSink);
        
        imgCaptureHandler.Manipulate(context =>
        {
            context.Apply(new SharpenProcessor());
        }, new ImageContext(MMALCameraConfig.StillResolution));
        
        // Camera warm up time
        await Task.Delay(2000);        
        await cam.ProcessAsync(cam.Camera.StillPort);
    }

    // Only call when you no longer require the camera, i.e. on app shutdown.
    cam.Cleanup();
}

Edge Detection

There are 3 modes available which provide different strengths of Edge Detection: EDStrength.Low, EDStrength.Medium and EDStrength.High.

public async Task TakePictureManual()
{                        
    MMALCamera cam = MMALCamera.Instance;

    using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/", "jpg"))
    using (var imgEncoder = new MMALImageEncoder())
    using (var nullSink = new MMALNullSinkComponent())
    {
        cam.ConfigureCameraSettings();
        
        var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.RGB24, 90);

        // Create our component pipeline.         
        imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
                
        cam.Camera.StillPort.ConnectTo(imgEncoder);                    
        cam.Camera.PreviewPort.ConnectTo(nullSink);
        
        imgCaptureHandler.Manipulate(context =>
        {
            context.Apply(new EdgeDetection(EDStrength.High));
        }, new ImageContext(MMALCameraConfig.StillResolution));
        
        // Camera warm up time
        await Task.Delay(2000);        
        await cam.ProcessAsync(cam.Camera.StillPort);
    }

    // Only call when you no longer require the camera, i.e. on app shutdown.
    cam.Cleanup();
}

Gaussian Blur

As per the Matrices available on the Wikipedia page, MMALSharp provides functionality for a 3x3 or 5x5 Gaussian Blur matrix convolution.

public async Task TakePictureManual()
{                        
    MMALCamera cam = MMALCamera.Instance;

    using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/", "jpg"))
    using (var imgEncoder = new MMALImageEncoder())
    using (var nullSink = new MMALNullSinkComponent())
    {
        cam.ConfigureCameraSettings();
        
        var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.RGB24, 90);

        // Create our component pipeline.         
        imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
                
        cam.Camera.StillPort.ConnectTo(imgEncoder);                    
        cam.Camera.PreviewPort.ConnectTo(nullSink);
        
        imgCaptureHandler.Manipulate(context =>
        {
            context.Apply(new GaussianProcessor(GaussianMatrix.Matrix3x3));
        }, new ImageContext(MMALCameraConfig.StillResolution));
        
        // Camera warm up time
        await Task.Delay(2000);        
        await cam.ProcessAsync(cam.Camera.StillPort);
    }

    // Only call when you no longer require the camera, i.e. on app shutdown.
    cam.Cleanup();
}

Strip Bayer Metadata

Use the following example to get raw access to the Bayer metadata produced with a JPEG frame. Ensure you pass in the correct camera version to the BayerMetaProcessor constructor, either CameraVersion.OV5647 or CameraVersion.IMX219.

public async Task TakePictureManual()
{                        
    MMALCamera cam = MMALCamera.Instance;

    using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/", "jpg"))
    using (var imgEncoder = new MMALImageEncoder(true))
    using (var nullSink = new MMALNullSinkComponent())
    {
        cam.ConfigureCameraSettings();
        
        var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.RGB24, 90);

        // Create our component pipeline.         
        imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
                
        cam.Camera.StillPort.ConnectTo(imgEncoder);                    
        cam.Camera.PreviewPort.ConnectTo(nullSink);
        
        imgCaptureHandler.Manipulate(context =>
        {
            context.Apply(new BayerMetaProcessor(CameraVersion.OV5647));
        }, new ImageContext(MMALCameraConfig.StillResolution));
        
        // Camera warm up time
        await Task.Delay(2000);        
        await cam.ProcessAsync(cam.Camera.StillPort);
    }

    // Only call when you no longer require the camera, i.e. on app shutdown.
    cam.Cleanup();
}

Custom convolution

By using the CustomConvolutionProcessor class, you can create your own custom kernel convolutions and have them applied to an image captured by MMALSharp. Simply pass in the kernel array, kernel width and height and the image will be modified accordingly.

private const int KernelWidth = 3;
private const int KernelHeight = 3;
private double[,] TopSobelKernel = new double[KernelWidth, KernelHeight]
{
    { 1, 2, 1 },
    { 0, 0, 0 },
    { -1, -2, -1 }
};

public async Task TakePictureManual()
{                        
    MMALCamera cam = MMALCamera.Instance;

    using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/", "jpg"))
    using (var imgEncoder = new MMALImageEncoder())
    using (var nullSink = new MMALNullSinkComponent())
    {
        cam.ConfigureCameraSettings();
        
        var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.RGB24, 90);

        // Create our component pipeline.         
        imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
                
        cam.Camera.StillPort.ConnectTo(imgEncoder);                    
        cam.Camera.PreviewPort.ConnectTo(nullSink);
        
        imgCaptureHandler.Manipulate(context =>
        {
            context.Apply(new CustomConvolutionProcessor(this.TopSobelKernel, KernelWidth, KernelHeight));
        }, new ImageContext(MMALCameraConfig.StillResolution));
        
        // Camera warm up time
        await Task.Delay(2000);        
        await cam.ProcessAsync(cam.Camera.StillPort);
    }

    // Only call when you no longer require the camera, i.e. on app shutdown.
    cam.Cleanup();
}