Görüntünün Ortalama Rengi


21

Bir resmin ortalama rengi

Bilim adamları , evrenin ortalama rengini belirleyebildiler ancak görüntüdeki ortalama rengi kaç byte bulabiliriz?

Senin görevin

Girişiniz, görüntüdeki renklerin ortalamasını bulmanız ve bir altıgen renk dizesi ( #??????) çıkarmanız gereken tek bir görüntü olacaktır . Görüntü aşağıdaki formatlardan herhangi biri olabilir.

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

Giriş, resme URL / URI olarak da alınabilir.

Ortalamaları hesaplayan veya bir kerede görüntüyü örnekleyen yerleşik işlevler ImageMeasurements izin verilmediği şekilde .

Örnekler

Sonuçlar, ortalamaları nasıl hesapladığınıza ve hangi renk modellerini kullandığınıza bağlı olarak biraz farklı olacaktır. Aşağıdaki resimler için RGB ve LCH (HSV) değerleri ekledim.

Örnek 1çıkış: #53715FRGB, ayrıca #3B7D3DLCH (HSV) olabilir


Örnek 2çıkış: #8B7D41RGB, #96753CLCH (HSV)


Hangi görüntü formatlarını ele almalıyız? Özellikle, sadece PPM işlemeyi seçebilir miyiz?
Dennis,

Daha küçük bir test davası alabilir miyim lütfen? Senaryom çok yavaş ve büyük davada çalıştırırken, yanlış olursa o zaman harcamam. Veya sadece hesapladığınız senaryoyu bile.
Maltysen

@Maltysen Bir 240x140 örneği ekledim. Umarım bu yeterince küçük
Downgoat

Hep aşağı inmeli miyiz? İlk örnekte, belirtilen çıktıda 95.6...yuvarladığınız 95.
Dennis,

4
PS En az 24 saat boyunca orada bırakmayacaksanız, kum havuzunda soru göndermenin bir anlamı yoktur , böylece diğer zaman dilimlerindeki insanlar bunu görebilir ve gerçekçi olarak 72 saat vermeniz gerekir çünkü herkes kontrol etmez takıntılı olarak kum havuzu.
Peter Taylor,

Yanıtlar:


19

Pyth - 23 22 19 18 16 bayt

Tüm kanalları elde etmek için geçiş yapar, daha sonra her birini toplar, böler ve küçültür. Birleştirerek ve hazırlayarak bitirir #.

+\#sm.H/sdldCs'z

Stdin'den bir görüntü dosyası adı (herhangi bir tür) alır ve stdout'a çıktılar. ÇOK YAVAŞ .

+               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

Örnek çalışma

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

Varsa, resim türünü belirtmek isteyebilirsiniz.
isaacg

1
@ isaacg iyi bir nokta. Her şeyi alır.
Maltysen

Bir şeyi nasıl alır, jpeg'i bir bitmap'e dekode eder mi?
Alec Teal

3
@AlecTeal göre dokümantasyon Pyth kontrolleri dosya bir görüntü olup olmadığını ve otomatik olarak bir bitmap dönüştürür. GitHub deposunda arama yapmak, PILgörüntüleri işlemek için kütüphaneyi kullanıyor gibi görünüyor . Tam kaynak için buraya bakın .
Bakuriu

@Bakuriu - Bu cevabı yükseltmedim, çünkü Pyth'un görüntüleri nasıl kullandığını ve bu yüzden bana biraz balık gibi göründüğünü bilmiyordum ... ama şimdi orada görüş sağladığın için bu benim oyumu alıyor. Açıklama için teşekkürler!
rayryeng

22

Bash, 46 bayt

ImageMagick, resmi görüntüdeki renklerin ortalamasını içeren bir piksele ölçeklendirir ve ardından metni metin olarak çıkarır.

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

4
Bu akıllı! +1
Maltysen

10

MATLAB - 68 bayt

Yüklemek istediğiniz görüntüyü seçmek için bir GUI açmak üzere görüntü ile imreadbirlikte okunur uigetfile. Bu kodla ilgili varsayım, tüm görüntülerin RGB olduğu ve ortalama rengi hesaplamak için her bir kanalın ayrı ayrı toplanıp bölüldüğüdür. birçok elemanlar olarak, RGB görüntü (piksel sayısı olan bir kanal içinde olduğu gibi ortalama kutu muhtemelen değişken nokta değerlerine oluşturmak için 3 bölünür), bir çağrı gereklidir sıfıra doğru numarayı yuvarlamak . onaltılık biçimlendirme dizesi ( ) ile birlikte ortalamadaki her tam sayı değerini onaltılı eşdeğerine yazdırmak için kullanılır. Bununla birlikte, herhangi bir kanalın ortalama değerinin 16'dan az olması durumunda, ekstra 0'ın sola doğru doldurulmasını sağlamak için vardır.numel(I)fixsprintf%x02* .

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

Örnek çalışır

Güzel olan şey imread, görüntüleri doğrudan URL’lerden okuyabilmeniz. Tekrarlanabilir bir örnek olarak, görüntüleri bilgisayarınıza indirdiğinizi ve yukarıdaki kodu çalıştırdığınızı varsayalım ... ancak gösterim için görüntüleri doğrudan Code Golf'tan okuyacağım:

İlk görüntü

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

ans =

#53715f

İkinci Resim

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

ans =

#8b7d41

* Not: Bu, MATLAB ve Octave sohbet odasında bulunan StackOverflow kullanıcıları tarafından yapılan ortak bir çabaydı .


7

CJam, 27 bayt

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

Bu, STDIN'den bir PPM görüntüsünü okur.

CJam'ın dahili görüntü işleme özelliği yoktur, bu nedenle bu kod tam 24 bit paletli (maksimum değer 255) bir ASCII Portable PixMap (sihirli sayı P3) bekler ve yorum yapmaz.

Test sürüşü

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

Nasıl çalışır

'#     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 bayt

Bu kazanmayacak ama yine de yaparken çok eğlendim.

HTML5 Canvas API'sini kullanır . Giriş, CORS özellikli bir görüntünün URL'sidir .

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``)}}

gösteri

ES6 olduğundan, şu anda yalnızca Firefox ve Edge’te çalışır.

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
Hey, doğrudan cevabınızda çalıştırılabilir olmasını seviyorum, çünkü HTML + JS :) +1.
rayryeng

Eğer yerini alamaz new Imageile Image()?
Ismael Miguel,

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

Bok. Ama yaratabilir W='width've H='height'kullanabilirsiniz i[H]ya dai[W]
Ismael Miguel

1
Daha fazla karakter kullanan
@IsmaelMiguel

6

Python [3] + SciPy, 144 133 121

Piksel verilerini yükler, her kanal için toplar, boyuta göre böler *, biçimler. Değerler sıfıra doğru yuvarlanır.

* size = width * height * kanal, böylece 3 ile çarpılır

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

1
Neden input()yola çıkmak için kullanmıyorsun ? Size 20 bayt kazandıracak.
Kade

Teşekkürler! Yine de 11 bayt kurtarmayı başardım.
Trang Oul

Sadece bir içe aktarmaya ihtiyacınız var import scipy. Değişim m.imreadiçin misc.imread.
Kade

Misc alma olmadan çalışmaz NameError: name 'misc' is not defined. Denenmiş from scipy import*, işe yaramadı.
Trang Oul

2
@TrangOul Ne hakkında from scipy import sum, misc as m? O zaman toplamı da kullandığınızda tasarruf edersiniz.
matsjoyce

3

R, 90 bayt

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

PNG dosyasının yolu STDIN'den okunur. Paket pngkurulmalı.

Adım adım:

#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 Bayt

Bir PPM dosyasını Alır hiçbir yorumlarla .

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));}

süreç

İlk kod:

#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;
}

Değişkenleri kırp ve döngüyü kaldır:

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;
}

Oradan çeşitli ifadeleri tek bir iade ifadesinde birleştirdim. Onu ve diğer herhangi bir yabancı tür bilgisini kaldırdı, değişkenleri yeniden adlandırdı ve boşlukları kesti.


2

Kobra - 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 bayt

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());}}

Bu cevabı sayesinde String.formatnumara için yığın taşması .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.