画像の平均色


21

画像の平均色

科学者は宇宙の平均を決定できましたが、画像の平均色は何バイトで見つけることができますか?

あなたのタスク

入力は単一の画像になり、画像内の色の平均を見つけて16進数の色文字列(#??????)を出力する必要があります。画像は次の形式のいずれかです。

  • JPEG / JFIF
    • JPEG 2000
  • TIFF
  • GIF
  • BMP
  • PNG
  • PNM
    • PPM

入力は、画像へのURL / URIとして取得することもできます。

ImageMeasurements許可されていないなど、平均を計算したり、一度に画像をサンプリングしたりする組み込み関数。

結果は、平均の計算方法と使用するカラーモデルによってわずかに異なります。下の画像にRGBとLCH(HSV)の値を追加しました。

サンプル1出力:#53715FRGB、#3B7D3DLCH(HSV)の場合もあります


サンプル2出力:#8B7D41RGB、#96753CLCH(HSV)


どの画像形式を処理する必要がありますか?具体的には、PPMのみを処理することを選択できますか?
デニス

もっと小さなテストケースをお願いできますか?私のスクリプトは非常に遅く、大規模なケースで実行しますが、間違っていてもその時間を無駄にしないでください。または、計算に使用したスクリプトだけです。
マルティセン

@Maltysen 240x140の例を追加しました。Hopfully小さな十分だという
Downgoat

常に切り捨てるべきですか?最初の例では95.6...95指定した出力で四捨五入した。
デニス

4
PS 少なくとも 24時間そこに残さない限り、サンドボックスに質問を投稿しても意味がありません。他のタイムゾーンの人々がそれを見ることができるようになります。強迫観念。
ピーターテイラー

回答:


19

パイス-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良い点。何でもかかります。
マルティセン

どのようにそれを取りますか、jpegをビットマップにデコードしますか?
アレックティール

3
@AlecTeal ドキュメントによると、Pythはファイルが画像かどうかをチェックし、自動的にビットマップに変換します。GitHubリポジトリを検索すると、PILライブラリを使用して画像を処理しているように見えます。正確なソースはこちらご覧ください。
バクリウ

@Bakuriu-Pythが画像を処理する方法を知らなかったので、この答えに賛成しませんでした。説明をありがとう!
rayryeng-モニカの復活

22

バッシュ、46バイト

ImageMagickは、画像内の色の平均を含む1ピクセルに画像をスケーリングし、テキストとして出力します。

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

4
それは賢い!+1
マルティセン

10

MATLAB-68バイト

画像は、とimread組み合わせて読み込まれuigetfile、GUIを開いてロードする画像を選択します。このコードでは、すべての画像がRGBであり、平均色を計算するために、各チャネルを個別に合計してから除算します。 RGB画像内の画素の総数(ある一つのチャネルであると同数の要素によって平均缶はおそらく浮動小数点値を生成するため3で割った値)の呼び出しは、ゼロに向かって下方数を丸めることが要求されます。16進フォーマット文字列()と組み合わせて、平均の各整数値を16進数に出力します。ただし、任意のチャネルの平均値が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

2番目の画像

>> 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には画像処理が組み込まれていないため、このコードは完全な24ビットパレット(最大値255)でコメントのないASCIIポータブル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 + 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-モニカの復元

あなたは置き換えることはできませんnew ImageImage()
イスマエルミゲル

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

がらくた。しかし、あなたが作成できるW='width'H='height'して使用i[H]またはi[W]
イスマエルミゲル

1
その用途より文字@IsmaelMiguel
rink.attendant.6

6

Python [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バイト節約できます。
ケード

ありがとう!しかし、なんとか11バイトを節約できました。
トランオウル

必要なインポートは1つだけですimport scipy。に変更m.imreadmisc.imreadます。
ケード

その他をインポートしないと機能しませんNameError: name 'misc' is not defined。試しましたがfrom scipy import*、どちらも動作しません。
トラン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;
}

そこから、さまざまなステートメントを1つの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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.