LoneRevenger
LoneRevenger

Reputation: 1

Averaging filter in image processing

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:

Image

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:

  1. I was referring to this topic: Averaging Filter using python;
  2. Using an averaging filter code from here, does, actually, blur an image, but it's blue for some reason. OpenCV

Update: Original Image

Upvotes: 0

Views: 2257

Answers (1)

Ricardo
Ricardo

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:

blurred image, mask 3x3

The result image for mask 5x5:

blurred image, mask 5x5

Upvotes: 2

Related Questions