在Javascript中计算RGB颜色块平均值的更有效方法

在Javascript中计算RGB颜色块平均值的更有效方法,javascript,math,Javascript,Math,我有一个对象数组,每个对象都有rgb值,我想得到通道的平均值 [{ r: 234, g: 250, b: 0 }, { r: 234, g: 250, b: 0 }, { r: 234, g: 250, b: 0 }] 直接的方法是通过数组进行映射,得到每个r、g和b值的总和,然后将每个值除以数组的长度 const arrLength = colorBlock.length let redArr = colorBlock.map(obj => obj.r) let greenArr

我有一个对象数组,每个对象都有rgb值,我想得到通道的平均值

[{ r: 234, g: 250, b: 0 },  { r: 234, g: 250, b: 0 }, { r: 234, g: 250, b: 0 }]
直接的方法是通过数组进行映射,得到每个r、g和b值的总和,然后将每个值除以数组的长度

const arrLength = colorBlock.length

let redArr = colorBlock.map(obj => obj.r)
let greenArr = colorBlock.map(obj => obj.g)
let blueArr = colorBlock.map(obj => obj.b)

const add = (total, num) => total + num;
const totalR = redArr.reduce(add, 0);
const totalG = greenArr.reduce(add, 0);
const totalB = blueArr.reduce(add, 0);

const averageR = parseInt(totalR / arrLength)
const averageG = parseInt(totalG / arrLength)
const averageB = parseInt(totalB / arrLength)
我的问题是,当我有一个大色块时,速度非常慢,一个900 x 900色块大约需要5秒钟。有没有更有效的方法


编辑:抱歉,伙计,我犯了一个错误,我的速度减慢的原因实际上来自创建色块的函数,而不是平均计算。计算只花了几百毫秒。

停止通道分离。一次遍历一个现有数组可能比创建和填充3个新数组(这本身意味着遍历原始数组3次)然后再次遍历所有数组更有效

let totals=colorBlock.reduce(
  (totals,current)=>{
    totals[0]+=current.r;
    totals[1]+=current.g;
    totals[2]+=current.b;
    return totals;
  },[0,0,0]);
let averageR=totals[0]/totals.length;
let averageG=totals[1]/totals.length;
let averageB=totals[2]/totals.length;

取消通道分离。一次遍历一个现有数组可能比创建和填充3个新数组(这本身意味着遍历原始数组3次)然后再次遍历所有数组更有效

let totals=colorBlock.reduce(
  (totals,current)=>{
    totals[0]+=current.r;
    totals[1]+=current.g;
    totals[2]+=current.b;
    return totals;
  },[0,0,0]);
let averageR=totals[0]/totals.length;
let averageG=totals[1]/totals.length;
let averageB=totals[2]/totals.length;
一次对整个对象使用
Array.reduce()
,然后使用
Array.map()
计算平均值:

const obj=[{r:200,g:161,b:1},{r:50,g:0,b:3},{r:50,g:0,b:5}]
常量还原=对象还原((acc,cur)=>{
acc[0]+=cur.r
acc[1]+=cur.g
acc[2]+=电流b
返回acc
},[0,0,0]).map(cur=>Math.round(cur/obj.length))
console.log(res)
一次对整个对象使用
Array.reduce()
,然后
Array.map()
计算平均值:

const obj=[{r:200,g:161,b:1},{r:50,g:0,b:3},{r:50,g:0,b:5}]
常量还原=对象还原((acc,cur)=>{
acc[0]+=cur.r
acc[1]+=cur.g
acc[2]+=电流b
返回acc
},[0,0,0]).map(cur=>Math.round(cur/obj.length))

log(res)
您的方法具有最佳的时间复杂度。您可以通过避免回调函数,并依靠普通的
for
循环(不是
中的
变量,而是普通的
)来获得速度:

const arrLength=colorBlock.length;
设totalR=0,totalG=0,totalB=0;
for(设i=0;i
您最多可以将处理900x900输入的时间减半,但仅此而已

要真正提高更多,您将需要依赖一些启发式,即大多数情况下相邻像素将具有大致相同的颜色代码。这样你就可以跳过像素了。这将给你一个估计的平均值,但这对于你的目的来说可能已经足够好了


备注:当参数为数字时,不要使用
parseInt
。这将不必要地将参数转换为字符串,只会将其转换回数字。相反,使用
Math.floor

您的方法具有最佳的时间复杂度。您可以通过避免回调函数,并依靠普通的
for
循环(不是
中的
变量,而是普通的
)来获得速度:

const arrLength=colorBlock.length;
设totalR=0,totalG=0,totalB=0;
for(设i=0;i
您最多可以将处理900x900输入的时间减半,但仅此而已

要真正提高更多,您将需要依赖一些启发式,即大多数情况下相邻像素将具有大致相同的颜色代码。这样你就可以跳过像素了。这将给你一个估计的平均值,但这对于你的目的来说可能已经足够好了


备注:当参数为数字时,不要使用
parseInt
。这将不必要地将参数转换为字符串,只会将其转换回数字。使用
Math.floor
使用简单的for循环代替
map
reduce
可以节省大量时间

//生成随机颜色
函数genColor(){
返回Math.floor(Math.random()*255);
}
const SIZE=500000;
const colorBlock=新数组(大小);
for(设i=0;iobj.r)
设greenArr0=colorBlock.map(obj=>obj.g)
设blueArr0=colorBlock.map(obj=>obj.b)
const add=(总数,num)=>total+num;
const totalR0=redArr0.reduce(add,0);
const totalG0=greenArr0.reduce(add,0);
const totalB0=blueArr0.reduce(add,0);
const averager 0=数学楼层(总计0/arrLength)
常数平均值G0=数学楼层(总计G0/长度)
const averageB0=数学楼层(总计B0/长度)
var endTime0=performance.now();
var totalR1=0;
var totalG1=0;
var totalB1=0;
for(设i=0;ilog(“for循环”,endTime1-endTime0)使用简单的for循环,而不是
map