이미지의 평균 색상


21

이미지의 평균 색상

과학자들은 우주 의 평균 색상 을 결정할 수 있었지만 이미지에서 평균 색상을 몇 바이트로 찾을 수 있습니까?

당신의 작업

입력 한 이미지는 이미지에서 평균 색상을 찾아 16 진수 색상 문자열 ( #??????)을 출력해야하는 단일 이미지입니다 . 이미지는 다음 형식 중 하나 일 수 있습니다.

  • JPEG / JFIF
    • JPEG 2000
  • 사소한 말다툼
  • GIF
  • BMP
  • PNG
  • PNM
    • PPM

입력은 이미지에 대한 URL / URI로도 취할 수 있습니다.

평균을 계산하거나 이미지를 한 번에 샘플링하는 내장 기능 ImageMeasurements은 허용되지 않습니다.

평균을 계산하는 방법과 사용하는 색상 모델에 따라 결과가 약간 다릅니다. 아래 이미지에 RGB 및 LCH (HSV) 값을 추가했습니다.

샘플 1출력 : #53715FRGB, #3B7D3DLCH (HSV) 일 수도 있음


샘플 2출력 : #8B7D41RGB, #96753CLCH (HSV)


어떤 이미지 형식을 처리해야합니까? 특히 PPM 만 처리하도록 선택할 수 있습니까?
데니스

더 작은 테스트 케이스를 가질 수 있습니까? 내 스크립트는 매우 느리며 큰 경우에 실행하지만 잘못된 경우 그 시간을 낭비하지 않습니다. 또는 당신이 그것을 계산 한 스크립트조차도.
Maltysen

@ Maltysen 240x140 예제를 추가했습니다.
다행히도

항상 반올림해야합니까? 첫 번째 예 에서 지정된 출력에서 95.6...반올림 한 95.
Dennis

4
추신 : 당신이 다른 시간대의 사람들이 그것을 볼 수 있도록 적어도 24 시간 동안 거기에 남겨 두지 않으면 샌드 박스에 질문을 게시 할 필요가 없습니다. 실제로 모든 사람들이 강박 적으로 샌드 박스.
피터 테일러

답변:


19

Pyth- 23 22 19 18 16 바이트

모든 채널을 얻기 위해 조옮김 한 다음 각 채널을 합산, 나누기 및 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

jpeg를 비트 맵으로 디코딩하는 방법은 무엇입니까?
Alec Teal

3
@AlecTeal 문서 에 따르면 Pyth는 파일이 이미지인지 확인하고 자동으로 비트 맵으로 변환합니다. GitHub 리포지토리를 검색하면 PIL라이브러리를 사용하여 이미지를 처리 하는 것처럼 보입니다 . 봐 여기에 정확한 소스.
Bakuriu

@Bakuriu-Pyth가 이미지를 처리하는 방법을 알지 못했기 때문에이 답변을 찬성하지 않았습니다. 설명 주셔서 감사합니다!
rayryeng-복원 모니카

22

배쉬, 46 바이트

ImageMagick은 이미지의 평균 색상을 포함하는 하나의 픽셀로 이미지의 크기를 조정 한 다음 텍스트로 출력합니다.

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

4
똑똑하다! +1
Maltysen

10

MATLAB-68 바이트

이미지가와에서 읽기 imread와 결합 uigetfile에 부하에 원하는 이미지를 선택하기 위해 GUI를 엽니 다.이 코드 가정은 모든 이미지는 RGB, 그리고 평균 색상을 계산하는 것입니다, 우리는 개별적으로 다음 나누어 각 채널을 통해 요약 RGB 이미지 ( ) 의 총 픽셀 수인 3을 3으로 나눈 한 채널에있는 요소 수 만큼. . 16 진 형식화 문자열 ( ) 과 결합 하여 평균적으로 각 정수 값을 16 진으로 인쇄하는 데 사용됩니다. 그러나 채널의 평균값이 16보다 작 으면 여분의 0이 왼쪽에 채워지도록합니다.numel(I)fixsprintf%x02* .

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

샘플 실행

좋은 점은 imreadURL에서 직접 이미지를 읽을 수 있다는 것입니다. 재현 가능한 예로, 컴퓨터에서 이미지를 다운로드하고 위의 코드를 실행했다고 가정 해 봅시다. 그러나 데모를 위해 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

* 참고 : 이는 MATLAB 및 Octave 대화방 에서 StackOverflow 사용자가 수행 한 공동 작업 입니다.


7

CJam, 27 바이트

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

STDIN에서 PPM 이미지를 읽습니다.

CJam에는 이미지 처리 기능이 내장되어 있지 않기 때문에이 코드는 완전한 24 비트 팔레트 (최대 값 255)와 주석이없는 ASCII Portable PixMap (매직 번호 P3)을 예상합니다.

시운전

$ 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 + 자바 스크립트 (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-복원 모니카

당신은 대체 할 수 없습니다 new Image와 함께 Image()?
Ismael Miguel

@IsmaelMiguelTypeError: Constructor Image requires 'new'
rink.attendant.6

쓰레기. 하지만 당신은 만들 수 W='width'H='height'사용할 i[H]또는i[W]
이스마엘 미구엘에게

1
@IsmaelMiguel 더 많은 문자를 사용합니다
rink.attendant.6

6

파이썬 [3] + SciPy, 144 (133) 121

픽셀 데이터를로드하고 각 채널의 합계를 크기 *로 나눕니다. 값은 0으로 반올림됩니다.

* size = width * height * 채널에 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 바이트를 절약 할 수 있습니다.
Kade

감사! 그래도 11 바이트를 절약했습니다.
Trang Oul

가져 오기가 하나만 필요합니다 import scipy. 변경 m.imreadmisc.imread.
Kade

기타 가져 오기 없이는 작동하지 않습니다 NameError: name 'misc' is not defined. 시도했지만 from scipy import*작동하지 않습니다.
Trang Oul

2
@TrangOul 어때 from scipy import sum, misc as m? 합계를 사용할 때도 저장합니다.
matsjoyce

3

R, 90 바이트

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

PNG 파일의 경로는 STDIN에서 읽습니다. 패키지 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;
}

거기서 나는 다양한 진술을 단일 반환 진술로 결합했습니다. 그것과 다른 불필요한 유형 정보를 제거하고 변수의 이름을 바꾸고 공백을 자릅니다.


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

자바, 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.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.