Reputation: 670
I am asking this question because I have a suggestion about https://pyimagesearch.com/2017/06/05/computing-image-colorfulness-with-opencv-and-python/
Here, they are citing Hasler and Süsstrunk’s 2003 paper, Measuring colorfulness in natural images. They are using NumPy to perform calculations but I'm a bit concerned about the speed at which one can compute the colorfulness of an image.
from imutils import build_montages
from imutils import paths
import numpy as np
import argparse
import imutils
import cv2
def image_colorfulness(image):
# split the image into its respective RGB components
(B, G, R) = cv2.split(image.astype("float"))
# compute rg = R - G
rg = np.absolute(R - G)
# compute yb = 0.5 * (R + G) - B
yb = np.absolute(0.5 * (R + G) - B)
# compute the mean and standard deviation of both `rg` and `yb`
(rbMean, rbStd) = (np.mean(rg), np.std(rg))
(ybMean, ybStd) = (np.mean(yb), np.std(yb))
# combine the mean and standard deviations
stdRoot = np.sqrt((rbStd ** 2) + (ybStd ** 2))
meanRoot = np.sqrt((rbMean ** 2) + (ybMean ** 2))
# derive the "colorfulness" metric and return it
return stdRoot + (0.3 * meanRoot)
Upvotes: 1
Views: 749
Reputation: 207345
I had a try at speeding this up, just by using OpenCV functions and got a 6.5x speed-up over your Numba version on my machine:
#!/usr/bin/env python3
import numpy as np
import cv2
from numba import *
def me(image,B,G,R):
# Use OpenCV methods wherever possible
rg = cv2.absdiff(R,G)
rgMean, rgStd = cv2.meanStdDev(rg)
avg = cv2.addWeighted(R, 0.5, G, 0.5, 0)
yb = cv2.absdiff(avg, B)
ybMean, ybStd = cv2.meanStdDev(yb)
# combine the mean and standard deviations
stdRoot = np.sqrt((rgStd ** 2) + (ybStd ** 2))
meanRoot = np.sqrt((rgMean ** 2) + (ybMean ** 2))
# derive the "colorfulness" metric and return it
return stdRoot + (0.3 * meanRoot), rgMean, rgStd, ybMean, ybStd
@njit(parallel=True)
def image_colorfulness(image,B,G,R):
# compute rg = R - G
rg = np.absolute(R - G)
# compute yb = 0.5 * (R + G) - B
yb = np.absolute(0.5 * (R + G) - B)
# compute the mean and standard deviation of both `rg` and `yb`
rgMean, rgStd = np.mean(rg), np.std(rg)
ybMean, ybStd = np.mean(yb), np.std(yb)
# combine the mean and standard deviations
stdRoot = np.sqrt((rgStd ** 2) + (ybStd ** 2))
meanRoot = np.sqrt((rgMean ** 2) + (ybMean ** 2))
# derive the "colorfulness" metric and return it
return stdRoot + (0.3 * meanRoot), rgMean, rgStd, ybMean, ybStd
image = cv2.imread('Oscars-selfie_620x349.png')
# OP's original method
B, G, R = cv2.split(image.astype("float"))
score, *others = image_colorfulness(image,B=B,G=G,R=R)
print(score, others)
%timeit image_colorfulness(image,B=B,G=G,R=R)
# Using OpenCV and avoiding promotion to float
B, G, R = cv2.split(image)
score, *others = me(image,B=B,G=G,R=R)
print(score, others)
%timeit me(image,B=B,G=G,R=R)
Timings for original and OpenCV methods
1.11 ms ± 43.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
171 µs ± 1.49 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Upvotes: 4