×
Namespaces

Variants
Actions

Sobel Edge Detection Custom Effect (Nokia Imaging SDK)

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how to create a Sobel Edge Detection custom effect. This is one of edge detection algorithms used for image processing.

SignpostIcon XAML 40.png
Article Metadata
Tested with
Devices(s): Nokia Lumia 920
Dependencies: Nokia Imaging SDK 1.0
Article
Created: Engin Kırmacı (19 Feb 2014)
Last edited: Engin Kırmacı (28 Feb 2014)

Contents

Introduction

The Sobel Edge Detection does help us to determine and separate objects from background in a clever way. An image gradient is a change in intensity (or color) of an image. An edge in an image occurs when the gradient is greatest and the Sobel operator makes use of this fact to find the edges in an image. The Sobel operator calculates the approximate image gradient of each pixel by convolving the image with a pair of 3×3 filters. These filters estimate the gradients in the horizontal (x) and vertical (y) directions and the magnitude of the gradient is simply the sum of these 2 gradients.

Sobel Masks

Source code

Full source code for the SobelEdgeDetection custom effect is provided below (toggle "Expand") and also in a ready-to-use file here: SobelEdgeDetection.cs.

SobelEdgeDetection.cs (28 Feb 2014)

  1. // ============================================================================
  2. // DATE        AUTHOR                   DESCRIPTION
  3. // ----------  -----------------------  ---------------------------------------
  4. // 2014.02.13  Engin.Kırmacı            Initial creation
  5. // 2014.02.28  Engin.Kırmacı            Removed unused property
  6. // ============================================================================
  7.  
  8. using Nokia.Graphics.Imaging;
  9.  
  10. namespace NISDKExtendedEffects.ImageEffects
  11. {
  12.     public class SobelEdgeDetection : CustomEffectBase
  13.     {
  14.         public SobelEdgeDetection(IImageProvider source)
  15.             : base(source)
  16.         {
  17.         }
  18.  
  19.         protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
  20.         {
  21.             var width = (int)sourcePixelRegion.Bounds.Width;
  22.             var height = (int)sourcePixelRegion.Bounds.Height;
  23.  
  24.             uint white = 0xff000000 | (255 << 16) | (255 << 8) | 255;
  25.             uint black = 0xff000000 | (0 << 16) | (0 << 8) | 0;
  26.  
  27.             int[,] gx = new int[,] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };
  28.             int[,] gy = new int[,] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } };
  29.  
  30.             int[,] allPixR = new int[width, height];
  31.             int[,] allPixG = new int[width, height];
  32.             int[,] allPixB = new int[width, height];
  33.  
  34.             int limit = 128 * 128;
  35.  
  36.             for (int i = 0; i < width; i++)
  37.                 for (int j = 0; j < height; j++)
  38.                     allPixR[i, j] = (byte)sourcePixelRegion.ImagePixels[j * width + i];
  39.  
  40.             int new_rx = 0, new_ry = 0;
  41.             int new_gx = 0, new_gy = 0;
  42.             int new_bx = 0, new_by = 0;
  43.             int rc, gc, bc;
  44.             for (int i = 1; i < width - 1; i++)
  45.             {
  46.                 for (int j = 1; j < height - 1; j++)
  47.                 {
  48.                     new_rx = 0;
  49.                     new_ry = 0;
  50.                     new_gx = 0;
  51.                     new_gy = 0;
  52.                     new_bx = 0;
  53.                     new_by = 0;
  54.                     rc = 0;
  55.                     gc = 0;
  56.                     bc = 0;
  57.  
  58.                     for (int wi = -1; wi < 2; wi++)
  59.                     {
  60.                         for (int hw = -1; hw < 2; hw++)
  61.                         {
  62.                             rc = allPixR[i + hw, j + wi];
  63.                             new_rx += gx[wi + 1, hw + 1] * rc;
  64.                             new_ry += gy[wi + 1, hw + 1] * rc;
  65.  
  66.                             gc = allPixG[i + hw, j + wi];
  67.                             new_gx += gx[wi + 1, hw + 1] * gc;
  68.                             new_gy += gy[wi + 1, hw + 1] * gc;
  69.  
  70.                             bc = allPixB[i + hw, j + wi];
  71.                             new_bx += gx[wi + 1, hw + 1] * bc;
  72.                             new_by += gy[wi + 1, hw + 1] * bc;
  73.                         }
  74.                     }
  75.                     if (new_rx * new_rx + new_ry * new_ry > limit || new_gx * new_gx + new_gy * new_gy > limit || new_bx * new_bx + new_by * new_by > limit)
  76.                         targetPixelRegion.ImagePixels[j * width + i] = white;
  77.                     else
  78.                         targetPixelRegion.ImagePixels[j * width + i] = black;
  79.                 }
  80.             }
  81.         }
  82.     }
  83. }

Testing

The Test Apps for Viewing Custom Filters allow you to cycle through a number of different custom effects (including SobelEdgeDetection) and apply them to the real-time camera preview or a static image.

In addition, the custom effect file can be dropped into your own project, and used as described in the section Using the filter.

Pre-requisites

Performance

Device SobelEdgeDetection
Lumia 920 1 FPS

The SobelEdgeDetection class runs 1 FPS (Frames Per Second).

Code walkthrough

Using the filter

Drop an image control into your XAML.

  1. <Image x:Name="FilterEffectImage" Width="800" Height="480" Stretch="Fill" Grid.RowSpan="2" />

Use this code to apply the filter effect to your chosen image and assign it to the XAML image control.

  1. // Initialize a WriteableBitmap with the dimensions of the XAML image control
  2. WriteableBitmap writeableBitmap = new WriteableBitmap((int)FilterEffectImage.Width, (int)FilterEffectImage.Height);
  3.  
  4. // Example: Accessing an image stream within a standard photo chooser task callback
  5. // http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394019(v=vs.105).aspx
  6. //using (var imageStream = new StreamImageSource(e.ChosenPhoto))
  7.  
  8. // Example: Accessing an image stream from a sample picture loaded with the project in a folder called "Pictures"
  9. var resource = App.GetResourceStream(new Uri(string.Concat("Pictures/", "sample_photo_08.jpg"), UriKind.Relative));
  10. using (var imageStream = new StreamImageSource(resource.Stream))
  11. {
  12.     // Applying the custom filter effect to the image stream
  13.     using (var customEffect = new SobelEdgeDetection(imageStream))
  14.     {
  15.         // Rendering the resulting image to a WriteableBitmap
  16.         using (var renderer = new WriteableBitmapRenderer(customEffect, writeableBitmap))
  17.         {
  18.             // Applying the WriteableBitmap to our xaml image control
  19.             FilterEffectImage.Source = await renderer.RenderAsync();
  20.         }
  21.     }
  22. }

License

The code has been released with the standard MIT License, and can be viewed in the Github project here.

Summary

Hopefully you've enjoyed seeing how to detect edges in an image using Sobel Edge Detection. This is just one of many things you can do with the amazing Nokia Imaging SDK.

As with all articles on the wiki, you are welcome to contribute any changes to this code that would improve the quality, whether it be additional features or improving its efficiency.

This page was last modified on 28 February 2014, at 13:03.
53 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×