图像的平均颜色


21

图片的平均颜色

科学家已经能够确定宇宙的平均颜色,但是我们可以在多少个字节中找到图像的平均颜色呢?

你的任务

您的输入将是一幅图像,您将需要查找图像中颜色的平均值并输出十六进制颜色字符串(#??????)。图像可以是以下任何格式

  • JPEG / JFIF
    • JPEG 2000
  • TIFF
  • GIF
  • 骨形态发生蛋白
  • PNG
  • PNM
    • PPM

输入也可以作为图像的URL / URI。

内置函数ImageMeasurements无法计算平均值或立即对图像进行采样。

例子

结果将略有不同,具体取决于您如何计算平均值和使用哪种颜色模型。我为下面的图像添加了RGB和LCH(HSV)值。

样品1输出:#53715FRGB,也可以是#3B7D3DLCH(HSV)


样品2输出:#8B7D41RGB,#96753CLCH(HSV)


我们必须处理什么图像格式?具体来说,我们可以选择仅处理PPM吗?
丹尼斯

请给我一个较小的测试用例吗?我的脚本非常慢,尽管我会在大型情况下运行它,但是如果出现错误,我不会浪费时间。甚至只是您用来计算的脚本。
马蒂森(Maltysen)2015年

@Maltysen我添加了一个240x140的示例。希望这足够小
Downgoat

我们应该总是四舍五入吗?在第一个示例中,95.6...您已经95在指定的输出中四舍五入为。
丹尼斯

4
PS:除非您要在沙盒中放置至少 24小时,否则在沙盒中发布问题是没有意义的,这样其他时区的人才能看到它,实际上,您需要给它72小时,因为并不是每个人都在检查沙盒迷恋。
彼得·泰勒

Answers:


19

Pyth- 23 22 19 18 16字节

转置以获得所有通道,然后求和,除法和十六进制化。通过串联和前置来完成#

+\#sm.H/sdldCs'z

从stdin获取图像文件名(任何类型),然后输出到stdout。非常慢

+               String concat
 \#             "#"
 s              String concat all channels
 m              Map
  .H            Hex string
    /  ld       Divided by length of channel
     sd         Sum of channel
  C             Transpose to separate into channels
   s            Concatenate all rows
    'z          Read image with filename input

样品运行

>>>pyth avg.pyth 
V5VAR.jpg
#8b7d41

您可能要指定图像类型(如果有)。
isaacg

1
@isaacg好点。需要什么。
马蒂森(Maltysen)2015年

它如何处理,将jpeg解码为位图?
亚历克·蒂尔

3
@AlecTeal根据文档, Pyth会检查文件是否为图像,并自动将其转换为位图。搜索GitHub存储库后,看起来好像使用该PIL库来处理图像。在此处查找确切的来源。
2015年

@Bakuriu-我没有赞成这个答案,因为我不知道Pyth是如何处理图像的,因此对我来说似乎有点可疑...但是,既然您在那里提供了见识,就可以得到我的投票。感谢您的澄清!
rayryeng-恢复莫妮卡2015年

22

Bash,46个字节

ImageMagick将图像缩放到一个像素,其中包含图像中颜色的平均值,然后将其输出为文本。

convert $1 -scale 1x1\! txt:-|egrep -o '#\w+'

4
太聪明了!+1
Maltysen

10

MATLAB-68个字节

读取图像并imread结合使用,uigetfile以打开GUI来选择要加载的图像。使用此代码的假设是所有图像均为RGB,并计算平均颜色,我们将每个通道分别求和,然后除以由尽可能多的元件,因为有在一个通道中,这是RGB图像(像素总数)除以3由于平均都不可能产生浮点值,将呼叫需要舍去朝向零的数目。与十六进制格式字符串()结合使用,可以将平均值中的每个整数值打印成十六进制等效值。但是,可以确保在任何通道的平均值小于16的情况下,在左侧填充额外的0。numel(I)fixsprintf%x02*

I=imread(uigetfile);
['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

样品运行

有趣的imread是,您可以直接从URL读取图像。作为可重现的示例,假设您已将图像下载到计算机上并运行了上面的代码...但是为了演示,我将直接从Code Golf中读取图像:

第一张图片

>> I=imread('http://i.stack.imgur.com/dkShg.jpg');
>> ['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

ans =

#53715f

第二张图片

>> I=imread('http://i.stack.imgur.com/V5VAR.jpg');
>> ['#' sprintf('%02x',fix(sum(sum(I))*3/numel(I)))]

ans =

#8b7d41

*注意:这是StackOverflow用户在MATLAB和Octave聊天室上的共同努力。


7

CJam,27个字节

'#[q~]5>3/_:.+\,f/"%02X"fe%

这将从STDIN读取PPM图像。

CJam没有内置图像处理功能,因此此代码需要ASCII便携式PixMap(魔术数P3),具有完整的24位调色板(最大值255)且没有注释。

测试运行

$ cjam avg.cjam < dkShg.ppm 
#53715F

怎么运行的

'#     e# Push that character.
[q~]   e# Evaluate the input and collect the results in an array.
5>     e# Discard the first first results (Pi, 3, width, height, range).
3/     e# Split into chunks of length 3 (RGB).
_:.+   e# Push a copy and add across the columns (RGB).
\,f/   e# Divide each sum by the length of the array (number of pixels).
"%02X" e# Push that format string (hexadecimal integer, zero-pad to two digits).
fe%    e# Format each integer, using the format string.

7

HTML5 + JavaScript(ES6),335字节

这不会赢,但我还是很开心。

使用HTML5 Canvas API。输入是启用CORS的图像的URL 。

f=(u,i=new Image)=>{i.crossOrigin='';i.src=u;i.onload=e=>{x=(c=document.createElement('canvas')).getContext('2d');a=w=c.width=i.width;a*=h=c.height=i.height;x.drawImage(i,0,0);for(d=x.getImageData(m=0,0,w,h).data,r=[0,0,0];m<d.length;m+=4){r[0]+=d[m];r[1]+=d[m+1];r[2]+=d[m+2]}console.log('#'+r.map(v=>(~~(v/a)).toString(16)).join``)}}

演示版

由于是ES6,因此目前仅在Firefox和Edge中可用。

f = (u,i = new Image) => {
  i.crossOrigin = '';
  i.src = u;
  i.onload = e => {
    x = (c = document.createElement('canvas')).getContext('2d');
    a = w = c.width = i.width;
    a *= h = c.height = i.height;
    x.drawImage(i, 0, 0);
    for (d = x.getImageData(m = 0, 0, w, h).data, r = [0, 0, 0]; m < d.length; m += 4) {
      r[0] += d[m]
      r[1] += d[m + 1];
      r[2] += d[m + 2];
    }
    console.log('#' + r.map(v => (~~(v/a)).toString(16)).join``)
  }
}

// Snippet stuff
console.log = x => document.body.innerHTML += x + '<br>';

f('http://crossorigin.me/https://i.stack.imgur.com/dkShg.jpg');

f('http://crossorigin.me/https://i.stack.imgur.com/V5VAR.jpg');


3
嘿,我喜欢它可以直接在您的答案中运行,因为它是HTML + JS :) +1。
rayryeng-恢复莫妮卡2015年

您不能替换new ImageImage()吗?
伊斯梅尔·米格尔

@IsmaelMiguelTypeError: Constructor Image requires 'new'
rink.attendant.15年

废话 但是您可以创建W='width'H='height'使用i[H]i[W]
Ismael Miguel 2015年

1
@IsmaelMiguel使用更多字符
rink.attendant.6

6

蟒[3] + SciPy的,144 133 121

加载像素数据,每个通道的总和,除以大小*,格式。值四舍五入为零。

*大小=宽度*高度*通道,因此乘以3

from scipy import misc,sum
i=misc.imread(input())
print('#'+(3*'{:2x}').format(*sum(i.astype(int),axis=(0,1))*3//i.size))

1
为什么不input()走这条路呢?它将为您节省20个字节。
卡德2015年

谢谢!我设法节省了11个字节。
董里2015年

您只需要一次导入,import scipy。更改m.imreadmisc.imread
卡德2015年

如果不导入misc,则无法正常工作NameError: name 'misc' is not defined。尝试过from scipy import*,也不起作用。
董里2015年

2
@TrangOul怎么样from scipy import sum, misc as m?然后,您也可以在使用sum时进行保存。
matsjoyce 2015年

3

R,90个字节

rgb(matrix(apply(png::readPNG(scan(,"")),3,function(x)sum(x*255)%/%length(x)),nc=3),m=255)

从STDIN读取PNG文件的路径。png需要安装软件包。

一步步:

#Reads path from stdin and feeds it to function readPNG from package png
p = png::readPNG(scan(,""))
#The result is a 3d matrix (1 layer for each color channel) filled with [0,1] values
#So next step, we compute the mean on each layer using apply(X,3,FUN)
#after moving the value to range [0,255] and keeping it as an integer.
a = apply(p,3,function(x)sum(x*255)%/%length(x))
#The result is then moved to a matrix of 3 columns:
m = matrix(a, nc=3)
#Which we feed to function rgb, while specifying that we're working on range [0,255]
rgb(m, m=255)

# Example:
rgb(matrix(apply(png::readPNG(scan(,"")),3,function(x)sum(x*255)%/%length(x)),nc=3),m=255)
# 1: ~/Desktop/dkShg.png
# 2: 
# Read 1 item
# [1] "#53715F"

2

C,259字节

接受无注释的PPM文件。

double*f,r,g,b;x,y,z,i;char*s="%d %d %d";main(a,_){(a-2)?(feof(f)?0:(fscanf(f,s,&x,&y,&z),r+=(x-r)/i,g+=(y-g)/i,b+=(z-b)/i++,main(0,0))):(f=fopen(((char**)_)[1],"r"),fscanf(f,"%*s%*d%*d%*d"),r=g=b=0.,i=1,main(0,0),printf(s,(int)r,(int)g,(int)b),fclose(f));}

处理

初始代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *f = fopen(argv[1],"r");
    int w,h,d,x,y,z,i;
    double r,g,b;
    fscanf(f,"%*s %d %d %d",&w,&h,&d);//get width, height, depth, ignore P6
    r = g = b = 0.0; //zero r, g, and b totals
    for (i=1; i<=w*h; ++i) {
        fscanf(f,"%d %d %d",&x,&y,&z);//get next pixel
        r+=(x-r)/i;//update averages
        g+=(y-g)/i;
        b+=(z-b)/i;
    }
    printf("%d %d %d",(int)r,(int)g,(int)b);//print result
    fclose(f);
    return 0;
}

修剪变量并删除循环:

double r,g,b;
FILE *f;
int i;
int main(int argc, char *argv[])
{
    if (argc==2) { // {./me} {file.ppm}
        f = fopen(argv[1],"r");
        fscanf(f,"%*s%*d%*d%*d");//drop info
        r = g = b = 0.0;
        i = 1;
        main(0,0);//begin load loop
        printf("%d %d %d",(int)r,(int)g,(int)b);
        fclose(f)
    } else {
        if (feof(f)) return 0;
        fscanf(f,"%d%d%d",&x,&y,&z);
        r+=(x-r)/i;
        g+=(y-g)/i;
        b+=(z-b)/i;
        i++;
        main(0,0);
    }
    return 0;
}

从那里,我将各种语句组合成单个return语句。删除了它和任何其他无关的类型信息,重命名了变量,并剪切了空白。


2

眼镜蛇-371

@ref 'System.Numerics'
use System.Drawing
use System.Numerics
class P
    def main
        i,d=Bitmap(Console.readLine?''),BigInteger
        r,g,b,c=d(),d(),d(),d()
        for x in i.width,for y in i.height,r,g,b,c=for n in 4 get BigInteger.add([r,g,b,c][n],d([(p=i.getPixel(x,y)).r,p.g,p.b,1][n]))
        print'#'+(for k in[r,g,b]get Convert.toString(BigInteger.divide(k,c)to int,16)).join('')

2

Java中,449个 447 446 430 426字节

import java.awt.*;interface A{static void main(String[]a)throws Exception{java.awt.image.BufferedImage i=javax.imageio.ImageIO.read(new java.io.File(new java.util.Scanner(System.in).nextLine()));int r=0,g=0,b=0,k=0,x,y;for(x=0;x<i.getWidth();x++)for(y=0;y<i.getHeight();k++){Color c=new Color(i.getRGB(x,y++));r+=c.getRed();g+=c.getGreen();b+=c.getBlue();}System.out.printf("#%06X",0xFFFFFF&new Color(r/k,g/k,b/k).getRGB());}}

多亏了这个在堆栈溢出上的答案String.format

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.