nipy
nipy

Reputation: 5508

Find average colour of each section of an image

I am looking for the best way to achieve the following using Python:

  1. Import an image.
  2. Add a grid of n sections (4 shown in this example below).
  3. For each section find the dominant colour.

sky

Desired output

Output an array, list, dict or similar capturing these dominant colour values.

Maybe even a Matplotlib graph showing the colours (like pixel art).

What have I tried?

The image could be sliced using image slicer:

import image_slicer
image_slicer.slice('image_so_grid.png', 4)

I could then potentially use something like this to get the average colour but Im sure there are better ways to do this.

What are the best ways to do this with Python?

Upvotes: 0

Views: 2861

Answers (2)

Juan
Juan

Reputation: 5768

You can use scikit-image's view_as_blocks together with numpy.mean. You specify the block size instead of the number of blocks:

import numpy as np
from skimage import data, util
import matplotlib.pyplot as plt

astro = data.astronaut()
blocks = util.view_as_blocks(astro, (8, 8, 3))

print(astro.shape)
print(blocks.shape)

mean_color = np.mean(blocks, axis=(2, 3, 4))

fig, ax = plt.subplots()
ax.imshow(mean_color.astype(np.uint8))

Output:

(512, 512, 3)
(64, 64, 1, 8, 8, 3)

blocked and averaged

Don't forget the cast to uint8 because matplotlib and scikit-image expect floating point images to be in [0, 1], not [0, 255]. See the scikit-image documentation on data types for more info.

Upvotes: 0

Robin Alvarenga
Robin Alvarenga

Reputation: 331

This works for 4 sections, but you'll need to figure out how to make it work for 'n' sections:

import cv2

img = cv2.imread('image.png')

def fourSectionAvgColor(image):
    rows, cols, ch = image.shape
    colsMid = int(cols/2)
    rowsMid = int(rows/2)

    numSections = 4
    section0 = image[0:rowsMid, 0:colsMid]
    section1 = image[0:rowsMid, colsMid:cols]
    section2 = image[rowsMid: rows, 0:colsMid]
    section3 = image[rowsMid:rows, colsMid:cols]
    sectionsList = [section0, section1, section2, section3]

    sectionAvgColorList = []
    for i in sectionsList:
        pixelSum = 0
        yRows, xCols, chs = i.shape
        pixelCount = yRows*xCols
        totRed = 0
        totBlue = 0
        totGreen = 0
        for x in range(xCols):
            for y in range(yRows):
                bgr = i[y,x]
                b = bgr[0]
                g = bgr[1]
                r = bgr[2]
                totBlue = totBlue+b
                totGreen = totGreen+g
                totRed = totRed+r

        avgBlue = int(totBlue/pixelCount)
        avgGreen = int(totGreen/pixelCount)
        avgRed = int(totRed/pixelCount)
        avgPixel = (avgBlue, avgGreen, avgRed)
        sectionAvgColorList.append(avgPixel)
    return sectionAvgColorList

print(fourSectionAvgColor(img))
cv2.waitKey(0)
cv2.destroyAllWindows()

Upvotes: 1

Related Questions