C# Tutorial: How To Use Log Transformation on Images
What is Log Transformation Anyway? Log transformation in image processing is a part of gray level transformations. It works by transforming each pixel individually. It is usually...
Filter by Category
What is Log Transformation Anyway? Log transformation in image processing is a part of gray level transformations. It works by transforming each pixel individually. It is usually...
Where Do We Start? There are numerous ways you can flip an image horizontally. It’s pretty basic functionality in image processing. I wanted to challenge myself and not just...
Let’s Get Started A very basic problem that we face in image processing is how to scale images without making them look deformed when we want to make it of an arbitrary...
List of contents: Short intro First Method – Google Opinion Rewards Second Method – Taking & Fortifying Gyms Third Method – Answer a Few Questions List of...
Zero padding an image is useful when we’re convolving it with a filter of certain size. How much padding should we use depends on how big our filter is. What is the purpose...
Gamma correction is a process, which allows you to set the brightness of screen. You can often run into this setting in video games, where you set the brightness of your screen...
A negative image is a complete inversion of an image, we would say to be normal. In other words, dark areas will appear light, and light areas will become dark. More in detail, a...
Gaussian blur is an image processing operation, that reduces noise in images. It does so by a convolution process, using a matrix that contains values calculated by a Gaussian...
Erosion is a morphological process, where pixels at an object boundaries are removed. Erosion and dilation are a pair of basic morphological transformations, which are completely...
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...
Log transformation in image processing is a part of gray level transformations. It works by transforming each pixel individually. It is usually the most useful for a use on grayscale images, hence the gray level transform expression.
So the first thing we need to do is transform our image into grayscale. I have already created a separate article on how we can convert our image into grayscale format.
Log transformation spreads the range of darker values and compresses the range of lighter shades. To achieve the opposite we would need to use inverse log transform.
We will be changing our pixels based on an equation that looks like
We are changing each pixel individually. So “s” and “r” variables represent pixel intensity values of output and input values respectively. “c” is a constant that controls our logarithmic curve, or in other words, it changes the expansion and compression of the ranges of darker and lighter intensity values.
That “+1” in the log function is added in case that the intensity value in the input is 0, we still get a usable value.
There’s already an article that covers how to change images into grayscale format, which goes a little bit more indepth of what’s going on.
private Bitmap Grayscale(Bitmap img) { int w = img.Width; int h = img.Height; BitmapData sd = img.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int bytes = sd.Stride * sd.Height; byte[] buffer = new byte[bytes]; byte[] result = new byte[bytes]; Marshal.Copy(sd.Scan0, buffer, 0, bytes); img.UnlockBits(sd); int current = 0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { current = y * sd.Stride + x * 4; int gray = (int)(buffer[current] * 0.0722 + buffer[current + 1] * 0.7152 + buffer[current + 2] * 0.2126); for (int i = 0; i < 3; i++) { result[current + i] = (byte)gray; } result[current + 3] = 255; } } Bitmap resimg = new Bitmap(w, h); BitmapData rd = resimg.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(result, 0, rd.Scan0, bytes); resimg.UnlockBits(rd); return resimg; }
private Bitmap LogTransform(Bitmap img, int constant) { int w = img.Width; int h = img.Height; img = Grayscale(img); BitmapData sd = img.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int bytes = sd.Stride * sd.Height; byte[] buffer = new byte[bytes]; byte[] result = new byte[bytes]; Marshal.Copy(sd.Scan0, buffer, 0, bytes); img.UnlockBits(sd); int current = 0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { current = y * sd.Stride + x * 4; for (int i = 0; i < 3; i++) { result[current + i] = (byte)(constant * Math.Log10(buffer[current + i] + 1)); } result[current + 3] = 255; } } Bitmap resimg = new Bitmap(w, h); BitmapData rd = resimg.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(result, 0, rd.Scan0, bytes); resimg.UnlockBits(rd); return resimg; }