Reputation: 1
I need a program that blurs an image, using averaging filter. It also must work with different sizes: 3x3, 5x5, etc.
Here is what I have:
import cv2
import numpy as np
from matplotlib import pyplot as plt
image = cv2.imread('tranquility.jpg')
#blur = cv2.blur(image,(3,3))
width = image.shape[1]
height = image.shape[0]
result = np.zeros((image.shape[0], image.shape[1]), dtype='uint8')
def meanFilter():
for row in range(height):
for col in range(width):
currentElement = 0;
left = 0;
right = 0;
top = 0;
bottom = 0;
topLeft = 0;
topRight = 0;
bottomLeft = 0;
bottomRight = 0;
counter = 1
currentElement = image[row][col]
if not col - 1 < 0:
left = image[row][col - 1]
counter += 1
if not col + 1 > width - 1:
right = image[row][col + 1]
counter += 1
if not row - 1 < 0:
top = image[row - 1][col]
counter += 1
if not row + 1 > height - 1:
bottom = image[row + 1][col]
counter += 1
if not row - 1 < 0 and not col - 1 < 0:
topLeft = image[row - 1][col - 1]
counter += 1
if not row - 1 < 0 and not col + 1 > width - 1:
topRight = image[row - 1][col + 1]
counter += 1
if not row + 1 > height - 1 and not col - 1 < 0:
bottomLeft = image[row + 1][col - 1]
counter += 1
if not row + 1 > height - 1 and not col + 1 > width - 1:
bottomRight = image[row + 1][col + 1]
counter += 1
total = int(currentElement) + int(left) + int(right) + int(top) + int(bottom) + int(topLeft) + int(
topRight) + int(bottomLeft) + int(bottomRight)
avg = total / counter
result[row][col] = avg
plt.subplot(121),plt.imshow(image),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(result),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
The output looks like this:
For some reason the original image is blue, though, it should have normal skin colour. In addition, Blurred version is plain purple colour. How can I modify the code so it blurs my image normally.
Additional info:
Update: Original Image
Upvotes: 0
Views: 2257
Reputation: 590
Your original image looks blueish because cv2.imread
returns an image with 3 channels in this order: blue, green and red. plt.imshow
works with RGB images, so you need to convert the original data:
bgr_image = cv2.imread(your_image_filename)
rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)
plt.imshow(rgb_image)
As stated by Romain, you would be better of using a library instead of coding your filter. In your particular case, cv2.blur
does exactly what you are looking for:
# 3x3 mask
blurred_image3 = cv2.blur(bgr_image, (3, 3))
cv2.imwrite('blurred_image3.png', blurred_image3)
# 5x5 mask
blurred_image5 = cv2.blur(bgr_image, (5, 5))
cv2.imwrite('blurred_image5.png', blurred_image5)
The result image for mask 3x3:
The result image for mask 5x5:
Upvotes: 2