计算特定坐标的每个 rgb 通道平均值的最快方法
fastet way to calculate mean of each rgb channel of specific coordinates
我为此构建了很多函数,最快的是:
meanRGB[:] = sum([img[i,j,:] for i,j in args])/len(args)
但这对于大图像来说仍然很慢。
一张 4700x3100 的图像大约需要 40 秒。(在旧的 cpu(第 4 代)上是 运行,但这并不重要)
args 包含特定 x,y
的二维坐标
[[0 0] [1 0] [2 1] ...]
更新
感谢所有发送这些伟大方法的好心人。我认为joostblack的方式是最快的。
在这里你可以模拟情况(缩短):
clusterMap = [[1,4,2],[1,2,3],[3,1,4]]
np.random.seed(2)
img = np.random.randint(low = 0, high = 255, size = (4700, 3100, 3))
segments = np.unique(clusterMap)
meanRGB = np.zeros((len(segments),3))
for k, segment in enumerate(segments.ravel()):
args = np.argwhere(clusterMap==segment)
meanRGB[k,:] = sum([img[i,j,:] for i,j in args])/len(args)
print(f"\n{meanRGB}")
按通道拆分,然后使用内置均值
r = np.mean(img[:,:,0])
g = np.mean(img[:,:,1])
b = np.mean(img[:,:,2])
如果您的列表不是您要使用
屏蔽的完整图像
mask = np.zeros_like(test[:,:,0])
x_coords = [c[0] for c in args]
y_coords = [c[1] for c in args]
mask[x_coords,y_coords] = 1
r = np.mean(test[mask==1][:,0])
g = np.mean(test[mask==1][:,1])
b = np.mean(test[mask==1][:,2])
您可以通过以下方式进行:
red_channel_mean = img[:, :, 0].mean()
green_channel_mean = img[:, :, 1].mean()
blue_channel_mean = img[:, :, 2].mean()
干杯
我试了一下。我认为这样更快,但我没有你的图像或你的 args
数组,所以我不确定。
import numpy as np
# Trying to recreate your situation
img = np.random.rand(4700,3100,3)
args = np.array([[2,3],[0,1],[2,4],[5,5]])
# my attempt
meanRGB = np.mean(img[args[:,0],args[:,1],:],axis=0)
print(meanRGB)
(示例)输出:
[0.68078292 0.4485302 0.46863616]
您可以将索引压缩在一起,屏蔽输入并计算平均值:
>>> img[tuple(zip(*args))].mean(0)
例如,给定 args
为:
>>> args
[[1, 0], [2, 1], [1, 4], [0, 2]]
>>> tuple(zip(*args))
((1, 2, 1, 0), (0, 1, 4, 2))
使用numba
的一种方式:
import numpy as np
from numba import njit, prange
img = np.random.randint(0, 256, (4700, 3100, 3))
args = np.random.randint(0, 1000, (100000, 2))
@njit(parallel=True, fastmath=True)
def average(array, indices):
n = len(indices)
sum_ = np.zeros(3)
for i in prange(n):
sum_ += array[indices[i][0], indices[i][1], :]
return sum_/n
验证:
op = sum(img[i,j,:] for i,j in args)/len(args)
numba_ = average(img, args)
np.isclose(op, numba_)
# array([ True, True, True])
基准测试(大约快几百倍):
%%timeit
meanRGB = sum(img[i,j,:] for i,j in args)/len(args)
# 124 ms ± 704 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit average(img, args)
# 136 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我为此构建了很多函数,最快的是:
meanRGB[:] = sum([img[i,j,:] for i,j in args])/len(args)
但这对于大图像来说仍然很慢。 一张 4700x3100 的图像大约需要 40 秒。(在旧的 cpu(第 4 代)上是 运行,但这并不重要)
args 包含特定 x,y
的二维坐标[[0 0] [1 0] [2 1] ...]
更新
感谢所有发送这些伟大方法的好心人。我认为joostblack的方式是最快的。 在这里你可以模拟情况(缩短):
clusterMap = [[1,4,2],[1,2,3],[3,1,4]]
np.random.seed(2)
img = np.random.randint(low = 0, high = 255, size = (4700, 3100, 3))
segments = np.unique(clusterMap)
meanRGB = np.zeros((len(segments),3))
for k, segment in enumerate(segments.ravel()):
args = np.argwhere(clusterMap==segment)
meanRGB[k,:] = sum([img[i,j,:] for i,j in args])/len(args)
print(f"\n{meanRGB}")
按通道拆分,然后使用内置均值
r = np.mean(img[:,:,0])
g = np.mean(img[:,:,1])
b = np.mean(img[:,:,2])
如果您的列表不是您要使用
屏蔽的完整图像mask = np.zeros_like(test[:,:,0])
x_coords = [c[0] for c in args]
y_coords = [c[1] for c in args]
mask[x_coords,y_coords] = 1
r = np.mean(test[mask==1][:,0])
g = np.mean(test[mask==1][:,1])
b = np.mean(test[mask==1][:,2])
您可以通过以下方式进行:
red_channel_mean = img[:, :, 0].mean()
green_channel_mean = img[:, :, 1].mean()
blue_channel_mean = img[:, :, 2].mean()
干杯
我试了一下。我认为这样更快,但我没有你的图像或你的 args
数组,所以我不确定。
import numpy as np
# Trying to recreate your situation
img = np.random.rand(4700,3100,3)
args = np.array([[2,3],[0,1],[2,4],[5,5]])
# my attempt
meanRGB = np.mean(img[args[:,0],args[:,1],:],axis=0)
print(meanRGB)
(示例)输出:
[0.68078292 0.4485302 0.46863616]
您可以将索引压缩在一起,屏蔽输入并计算平均值:
>>> img[tuple(zip(*args))].mean(0)
例如,给定 args
为:
>>> args
[[1, 0], [2, 1], [1, 4], [0, 2]]
>>> tuple(zip(*args))
((1, 2, 1, 0), (0, 1, 4, 2))
使用numba
的一种方式:
import numpy as np
from numba import njit, prange
img = np.random.randint(0, 256, (4700, 3100, 3))
args = np.random.randint(0, 1000, (100000, 2))
@njit(parallel=True, fastmath=True)
def average(array, indices):
n = len(indices)
sum_ = np.zeros(3)
for i in prange(n):
sum_ += array[indices[i][0], indices[i][1], :]
return sum_/n
验证:
op = sum(img[i,j,:] for i,j in args)/len(args)
numba_ = average(img, args)
np.isclose(op, numba_)
# array([ True, True, True])
基准测试(大约快几百倍):
%%timeit
meanRGB = sum(img[i,j,:] for i,j in args)/len(args)
# 124 ms ± 704 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit average(img, args)
# 136 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)