I am writing a python script that would use a 3x3 kernel to convert an image from color to grayscale.
I created a function that takes an 'image' and a 'kernel' as parameters, and returns the grayscale version of the image.
Inside of the function I split the image into 3 individual channels: redChannel, greenChannel, and blueChannel.
Then I take an average of these three channels as such: image = (red + green + blue) / 3
.
I stored the values for Image height and width as follows: (Hi, Wi) = image.shape[:2]
and I did the same for storing the height and width of the kernel, (Hk, Wk) = kernel.shape[:2]
.
I also included the padding for the image so that the kernel would not run out of bounds
pad = (Wk - 1) // 2
.
Then I created two for loops that would iterate across height and width of the image using Hi
and Wi
.
Inside of the for loops, I reshaped the image into so that I could multiply it with the kernel. Then I store the computed result in an output array.
This is the full code:
from skimage.exposure import rescale_intensity
import numpy as np
import cv2
def convolve(image, kernel):
(Hi, Wi) = image.shape[:2]
(Hk, Wk) = kernel.shape[:2]
red, green, blue = cv2.split(image)
image = (red + green + blue) / 3
pad = (Wk - 1) // 2
image = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REPLICATE)
output = np.zeros((Hi, Wi), dtype="float32")
for y in range(Hi, Hk + pad):
for x in range(Wi, Wk + pad):
roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]
k = (roi * kernel).sum()
output[y - pad, x - pad] = k
output = rescale_intensity(output, in_range=(0, 255))
output = (output * 255).astype("uint8")
return output
image = cv2.imread("mandrill.png")
kernel = np.ones((3, 3)) * (1/3)
cv2.imshow("Output", convolve(image, kernel))
cv2.waitKey(0)
cv2.destroyAllWindows()
I cannot seem to find any issues with the code, but the result is a black screen. Any help will be greatly appreciated))
I found the answer using a slightly different approach.
This methods gets the pixel values of the image and stores it in 3 color channels (R,G,B). The res = np.dot(kernel, v)
multiplies the image with a 3x3 grayscale kernel. The three if statements
rescale the intensity of the pixel values.
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
def convolve(img, kernel):
width, height = img.size
pixels = img.load()
for py in range(height):
for px in range(width):
r, g, b = img.getpixel((px, py))
v = np.array([[r], [g], [b]])
res = np.dot(kernel, v)
tr, tg, tb = int(res[0, 0]), int(res[1, 0]), int(res[2, 0])
if tr > 255:
tr = 255
if tg > 255:
tg = 255
if tb > 255:
tb = 255
pixels[px, py] = (tr, tg, tb)
return img
img = Image.open('mandrill.jpg')
grayscale = np.ones((3, 3)) * (1/3)
convolve(img, grayscale)
plt.imshow(img)