C# Tutorial: How To Apply Dilation To An Image
Dilation is a simple morphology process which changes pixel intensities based on the change of intensities that occur at object boundaries. This process is used on grayscale...
Filter by Category
Dilation is a simple morphology process which changes pixel intensities based on the change of intensities that occur at object boundaries. This process is used on grayscale images, where pixel values across all color channels are the same.
When we apply dilation to an image, our goal is to highlight a certain object. It works by setting a kernel on a certain set of pixels, where only the center pixel is under the process of being changed or not. Using neighboring pixels we only detect, if intensities of those are different than the center one. If there is a difference, then the highest of all of those intensities is set to the intensity of the center pixel.
Kernel holds values of 0s and 1s, with which we can form different forms. Most common form used is cross or in kernels of higher dimensions, diamond shapes. In this project, created for this tutorial, I used a kernel of size 3×3, which holds values in a cross formation.
If a kernel is in a position where center pixel intensity is the same as intensities from all neighboring pixels which hold a certain formation, the pixel intensity doesn’t change.
Here is the beginning of the function, through which we pass two parameters, our image and dimension of our kernel.
private Bitmap Morph(Bitmap srcImg, int kernelSize) {
//Create image dimension variables for convenience int width = srcImg.Width; int height = srcImg.Height; //Lock bits to system memory for fast processing Rectangle canvas = new Rectangle(0, 0, width, height); BitmapData srcData = srcImg.LockBits(canvas, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int stride = srcData.Stride; int bytes = stride * srcData.Height; //Create byte arrays that will hold all pixel data, one for processing, one for output byte[] pixelBuffer = new byte[bytes]; byte[] resultBuffer = new byte[bytes]; //Write pixel data to array meant for processing Marshal.Copy(srcData.Scan0, pixelBuffer, 0, bytes); srcImg.UnlockBits(srcData);
//Convert to grayscale float rgb = 0; for (int i = 0; i < bytes; i+=4) { rgb = pixelBuffer[i] * .071f; rgb += pixelBuffer[i + 1] * .71f; rgb += pixelBuffer[i + 2] * .21f; pixelBuffer[i] = (byte)rgb; pixelBuffer[i + 1] = pixelBuffer[i]; pixelBuffer[i + 2] = pixelBuffer[i]; pixelBuffer[i + 3] = 255; }
int kernelDim = kernelSize; //This is the offset of center pixel from border of the kernel int kernelOffset = (kernelDim - 1) / 2; int calcOffset = 0; int byteOffset = 0; for (int y = kernelOffset; y < height - kernelOffset; y++) { for (int x = kernelOffset; x < width - kernelOffset; x++) { byte value = 0; byteOffset = y * stride + x * 4; //Apply dilation for (int ykernel = -kernelOffset; ykernel <= kernelOffset; ykernel++) { for (int xkernel = -kernelOffset; xkernel <= kernelOffset; xkernel++) { if (shape[ykernel + kernelOffset, xkernel + kernelOffset] == 1) { calcOffset = byteOffset + ykernel * stride + xkernel * 4; value = Math.Max(value, pixelBuffer[calcOffset]); } else { continue; } } } //Write processed data into the second array resultBuffer[byteOffset] = value; resultBuffer[byteOffset + 1] = value; resultBuffer[byteOffset + 2] = value; resultBuffer[byteOffset + 3] = 255; } }
//Create output bitmap of this function Bitmap rsltImg = new Bitmap(width, height); BitmapData rsltData = rsltImg.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); //Write processed data into bitmap form Marshal.Copy(resultBuffer, 0, rsltData.Scan0, bytes); rsltImg.UnlockBits(rsltData); return rsltImg; }
private byte[,] shape { get { return new byte[,] { { 0, 1, 0 }, { 1, 1, 1 }, { 0, 1, 0 } }; } }
I enjoyed making this tutorial, there were many new things I learned along the way. Dilation process is very good to use in combination with another process called holes filling.
And of course, I would love to read what you think about it. There is a comment section below, don’t be shy, I don’t bite.
Comments
I see interesting posts here. Your site can go viral easily, you need some initial
traffic only. There is a sneaky method to get massive traffic from social sites.
Search in google for; Twinor’s strategy
https://epochabuse.com is my favorite now
Very good website – bookmarked
Greetings! Really helpful advice on this post!
It really is the small changes that make the largest changes.
Thanks a lot for sharing!
Pretty! This was a really amazing post. Thank
you for your provided information
I love it when people come together and share views, great blog,
keep it up.
Hi, just wanted to say, I enjoyeɗ this blog post.
It was helρfսl. Keep on рosting!
Thank you for any other informative website.
The plаce else may just I am getting that kind of info writtеn in such an ideal
means? I have a project that I am ѕimply now working on, and I have been at the glance out for such
information.
Ꮢemarkable! Its genuinely amazing piece of writing,
I have got much clear idea about from this p᧐st.
This eⲭcellent website truly has all the information and fɑcts I needed about
this subjeсt and didn’t know who to ask.
Awesome artіcle.
Ⅴery great post. I just stᥙmbled upon your webⅼⲟg and wished to say that I have truly loved suгfing around your bⅼog posts.
In any casе Ι wіll be suЬscribing to your гss fеed and I hope you write again soon!
I аm genuinely happy to read this blog posts which incluɗes lots of valuable facts, thanks for providing such information.
Hi, this weeкend is pleasant for me, for the геason that this
moment i am reading this enormoսs educational paragraph here аt my house.
I mսst thаnk you for the efforts you have put
in penning this site. I am hoping to view the same high-grade content by уou in the future as weⅼl.
In tгuth, yoսr creative writing abilities has inspired
me to get my own site now 😉