Basic Image Manipulation

[CG]Maxime
3,754 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content
Previous: Colors

Filtering

A lot of image processing algorithms rely on the convolution between a kernel (typicaly a 3x3 or 5x5 matrix) and an image. This may sound scary to some of you but that's not as difficult as it sounds:

Let's take a 3x3 matrix as our kernel. For each pixel, the filter multiplies the current pixel value and the other 8 surrounding pixels by the kernel corresponding value. Then it adds the result to get the value of the current pixel. Let's see an example:

Matrix convolution

In this example, the value of each pixel is equal to the double of the pixel that was located above it (e.g. 92 = 46 x 2).

Blur

A simple blur can be done using this kernel:

19[111111111]

This is called the Box Blur. Each pixel is computed as the average of the surrounding pixels.

And here is the kernel for the Gaussian Blur:

1256[1464141624164624362464162416414641]

As you can see, it's a weighted mean of the surrounding pixels that gives more weight to the pixel near the current pixel.

Blur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from PIL import Image, ImageDraw
# Load image:
input_image = Image.open("input.png")
input_pixels = input_image.load()
# Box Blur kernel
box_kernel = [[1 / 9, 1 / 9, 1 / 9],
[1 / 9, 1 / 9, 1 / 9],
[1 / 9, 1 / 9, 1 / 9]]
# Gaussian kernel
gaussian_kernel = [[1 / 256, 4 / 256, 6 / 256, 4 / 256, 1 / 256],
[4 / 256, 16 / 256, 24 / 256, 16 / 256, 4 / 256],
[6 / 256, 24 / 256, 36 / 256, 24 / 256, 6 / 256],
[4 / 256, 16 / 256, 24 / 256, 16 / 256, 4 / 256],
[1 / 256, 4 / 256, 6 / 256, 4 / 256, 1 / 256]]
# Select kernel here:
kernel = box_kernel
# Middle of the kernel
offset = len(kernel) // 2
# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)
# Compute convolution between intensity and kernels
for x in range(offset, input_image.width - offset):
for y in range(offset, input_image.height - offset):
acc = [0, 0, 0]
for a in range(len(kernel)):
for b in range(len(kernel)):
xn = x + a - offset
yn = y + b - offset
pixel = input_pixels[xn, yn]
acc[0] += pixel[0] * kernel[a][b]
acc[1] += pixel[1] * kernel[a][b]
acc[2] += pixel[2] * kernel[a][b]
draw.point((x, y), (int(acc[0]), int(acc[1]), int(acc[2])))
output_image.save("output.png")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Edge detection

There are multiple ways to do edge detection. We will present the Sobel Operator here.

The Sobel Operator uses two kernels (one for each direction): Kx=[101202101] and Ky=[121000121].

We compute the convolution between the image (converted in black and white) and the two kernels separately. That gives us, for each pixel, the values magx and magy. The value of the current pixel is set at magx2+magy2.

Sobel operator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from PIL import Image, ImageDraw
from math import sqrt
# Load image:
input_image = Image.open("input.png")
input_pixels = input_image.load()
# Calculate pixel intensity as the average of red, green and blue colors.
intensity = [[sum(input_pixels[x, y]) / 3 for y in range(input_image.height)] for x in range(input_image.width)]
# Sobel kernels
kernelx = [[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]]
kernely = [[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]]
# Create output image
output_image = Image.new("RGB", input_image.size)
draw = ImageDraw.Draw(output_image)
# Compute convolution between intensity and kernels
for x in range(1, input_image.width - 1):
for y in range(1, input_image.height - 1):
magx, magy = 0, 0
for a in range(3):
for b in range(3):
xn = x + a - 1
yn = y + b - 1
magx += intensity[xn][yn] * kernelx[a][b]
magy += intensity[xn][yn] * kernely[a][b]
# Draw in black and white the magnitude
color = int(sqrt(magx**2 + magy**2))
draw.point((x, y), (color, color, color))
output_image.save("output.png")
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content