Warna Rata-Rata suatu Gambar

21

Warna rata-rata suatu gambar

Para ilmuwan telah dapat menentukan warna rata-rata alam semesta, tetapi dalam berapa banyak byte yang dapat kita temukan warna rata-rata pada suatu gambar?

Tugas Anda

Input Anda akan menjadi gambar tunggal yang Anda perlu menemukan rata-rata warna dalam gambar dan menghasilkan string warna hex ( #??????). Gambar dapat berupa salah satu format berikut

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

Input juga dapat diambil sebagai URL / URI ke gambar.

Fungsi bawaan yang menghitung rata-rata atau sampel gambar sekaligus seperti ImageMeasurementsitu tidak diizinkan.

Contohnya

Hasil akan sedikit berbeda tergantung pada bagaimana Anda menghitung rata-rata dan model warna yang Anda gunakan. Saya telah menambahkan nilai RGB dan LCH (HSV) untuk gambar di bawah ini.

Contoh 1output: #53715FRGB, mungkin juga #3B7D3DLCH (HSV)


Contoh 2output: #8B7D41RGB, #96753CLCH (HSV)

Downgoat
sumber
Format gambar apa yang harus kita tangani? Secara khusus, dapatkah kita memilih untuk hanya menangani PPM?
Dennis
Bisakah saya memiliki test case yang lebih kecil? Script saya sangat lambat, dan sementara saya akan menjalankannya pada case besar, saya tidak membuang waktu jika itu salah. Atau bahkan hanya skrip Anda menghitungnya.
Maltysen
@Maltysen Saya telah menambahkan contoh 240x140. Semoga itu cukup kecil
Downgoat
Haruskah kita selalu membulatkan tekad? Dalam contoh pertama 95.6...,, yang telah Anda bulatkan ke 95dalam output yang ditentukan.
Dennis
4
PS Tidak ada gunanya memposting pertanyaan di kotak pasir kecuali Anda akan membiarkannya di sana selama setidaknya 24 jam, sehingga orang-orang di zona waktu lain dapat melihatnya, dan secara realistis Anda perlu memberikannya 72 jam karena tidak semua orang memeriksa kotak pasir secara obsesif.
Peter Taylor

Jawaban:

19

Pyth - 23 22 19 18 16 byte

Transposes untuk mendapatkan semua saluran, lalu jumlahkan, bagi, dan hubungkan masing-masing. Selesai dengan menyatukan dan mengawali a #.

+\#sm.H/sdldCs'z

Mengambil nama file gambar (tipe apa saja) dari stdin dan output ke stdout. SANGAT LAMBAT .

+               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

Contoh dijalankan

>>>pyth avg.pyth 
V5VAR.jpg
#8b7d41
Maltysen
sumber
Anda mungkin ingin menentukan jenis gambar, jika ada.
isaacg
1
@isaacg poin bagus. Dibutuhkan apa saja.
Maltysen
Bagaimana cara mengambil sesuatu, apakah itu memecahkan kode jpeg ke bitmap?
Alec Teal
3
@AlecTeal Menurut dokumentasi Pyth memeriksa apakah file tersebut adalah gambar dan secara otomatis mengubahnya menjadi bitmap. Mencari repositori GitHub sepertinya menggunakan PILperpustakaan untuk menangani gambar. Lihat di sini untuk sumber yang tepat.
Bakuriu
@ Bakuriu - Saya tidak menjawab pertanyaan ini karena saya tidak tahu bagaimana Pyth menangani gambar sehingga terlihat agak mencurigakan bagi saya ... tapi sekarang setelah Anda memberikan wawasan di sana, ini memberikan suara saya. Terimakasih atas klarifikasinya!
rayryeng
22

Bash, 46 byte

ImageMagick mengubah skala gambar menjadi satu piksel yang berisi rata-rata warna dalam gambar kemudian mengeluarkannya sebagai teks.

convert $1 -scale 1x1\! txt:-|egrep -o '#\w+'
SteelRaven
sumber
4
Itu pintar! +1
Maltysen
10

MATLAB - 68 byte

Gambar dibaca bersama imreaddengan uigetfileuntuk membuka GUI untuk memilih gambar yang ingin Anda muat. Asumsi dengan kode ini adalah bahwa semua gambar adalah RGB, dan untuk menghitung warna rata-rata, kami menjumlahkan masing-masing saluran secara individu kemudian membagi oleh sebanyak mungkin elemen dalam satu saluran, yang merupakan jumlah total piksel dalam gambar RGB ( ) dibagi dengan 3. Karena rata-rata dapat menghasilkan nilai titik apung, panggilan ke diperlukan untuk membulatkan angka ke bawah ke nol . dikombinasikan dengan string format heksadesimal ( ) digunakan untuk mencetak setiap nilai integer dalam rata-rata menjadi setara hex-nya. Namun, ada untuk memastikan bahwa 0 ekstra empuk ke kiri jika nilai rata-rata untuk setiap saluran kurang dari 16numel(I)fixsprintf%x02* .

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

Contoh Berjalan

Yang menyenangkan imreadadalah Anda bisa membaca gambar langsung dari URL. Sebagai contoh yang dapat direproduksi, anggap Anda telah mengunduh gambar di komputer Anda dan telah menjalankan kode di atas ... tetapi untuk demonstrasi, saya akan membaca gambar langsung dari Code Golf:

Gambar pertama

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

ans =

#53715f

Gambar kedua

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

ans =

#8b7d41

* Catatan: Ini adalah upaya kolaborasi yang dilakukan oleh pengguna StackOverflow di ruang obrolan MATLAB dan Oktaf .

rayryeng - Reinstate Monica
sumber
7

CJam, 27 byte

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

Ini membaca gambar PPM dari STDIN.

CJam tidak memiliki pemrosesan gambar bawaan, jadi kode ini mengharapkan ASCII Portable PixMap (nomor ajaib P3) dengan palet 24-bit penuh (nilai maksimum 255) dan tidak ada komentar.

Uji coba

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

Bagaimana itu bekerja

'#     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.
Dennis
sumber
7

HTML5 + JavaScript (ES6), 335 byte

Ini tidak akan menang, tetapi saya senang melakukannya.

Menggunakan HTML5 Canvas API . Input adalah URL dari gambar yang mendukung CORS .

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

Demo

Karena ES6, saat ini hanya berfungsi di Firefox dan 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');

rink.attendant.6
sumber
3
Hai, saya suka itu bisa dijalankan langsung di jawaban Anda karena itu HTML + JS :) +1.
rayryeng
Tidak bisakah Anda ganti new Imagedengan Image()?
Ismael Miguel
@IsmaelMiguelTypeError: Constructor Image requires 'new'
rink.attendant.6
Sampah. Tetapi Anda dapat membuat W='width'dan H='height'menggunakan i[H]ataui[W]
Ismael Miguel
1
@IsmaelMiguel Yang menggunakan lebih banyak karakter
rink.attendant.6
6

Python [3] + SciPy, 144 133 121

Memuat data piksel, jumlah untuk setiap saluran, dibagi menurut ukuran *, format. Nilai dibulatkan ke nol.

* ukuran = lebar * tinggi * saluran, sehingga dikalikan dengan 3

from scipy import misc,sum
i=misc.imread(input())
print('#'+(3*'{:2x}').format(*sum(i.astype(int),axis=(0,1))*3//i.size))
Trang Oul
sumber
1
Mengapa tidak digunakan input()untuk mengambil jalan? Ini akan menghemat 20 byte.
Kade
Terima kasih! Saya sudah berhasil menghemat 11 byte.
Trang Oul
Anda hanya perlu satu impor import scipy,. Ubah m.imreadke misc.imread.
Kade
Tidak berfungsi tanpa mengimpor misc NameError: name 'misc' is not defined,. Sudah mencoba from scipy import*, juga tidak berhasil.
Trang Oul
2
@ TrangOul Bagaimana from scipy import sum, misc as m? Anda menghemat saat Anda menggunakan jumlah juga, lalu.
matsjoyce
3

R, 90 byte

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

Path ke file PNG dibaca dari STDIN. Paket pngperlu diinstal.

Selangkah demi selangkah:

#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"
plannapus
sumber
2

C, 259 Bytes

Mengambil file PPM tanpa komentar .

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

Proses

Kode awal:

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

Potong variabel dan hapus loop:

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

Dari sana saya menggabungkan berbagai pernyataan menjadi satu pernyataan pengembalian. Dihapus dan info jenis asing lainnya, variabel berubah nama, dan memotong spasi.

LambdaBeta
sumber
2

Cobra - 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('')
Suram
sumber
2

Java, 449 447 446 430 426 byte

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

Terima kasih atas jawaban ini pada stack overflow untuk String.formattriknya.

SuperJedi224
sumber