Couleur moyenne d'une image

21

Couleur moyenne d'une image

Les scientifiques ont pu déterminer la couleur moyenne de l'univers mais en combien d'octets pouvons-nous trouver la couleur moyenne sur une image?

Ta tâche

Votre entrée sera une seule image dont vous aurez besoin pour trouver la moyenne des couleurs dans l'image et produire une chaîne de couleurs hexadécimale ( #??????). L'image peut être l'un des formats suivants

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

L'entrée peut également être considérée comme une URL / URI de l'image.

Fonctions intégrées qui calculent des moyennes ou échantillonnent l'image à la fois comme celles ImageMeasurementsqui ne sont pas autorisées.

Exemples

Les résultats différeront légèrement selon la façon dont vous calculez la moyenne et les modèles de couleurs que vous utilisez. J'ai ajouté des valeurs RVB et LCH (HSV) pour les images ci-dessous.

Échantillon 1sortie: #53715FRVB, peut également être #3B7D3DLCH (HSV)


Échantillon 2sortie: #8B7D41RGB, #96753CLCH (HSV)

Downgoat
la source
Quels formats d'image devons-nous gérer? Plus précisément, pouvons-nous choisir de gérer uniquement PPM?
Dennis
Puis-je avoir un cas de test plus petit s'il vous plaît? Mon script est très lent, et bien que je l'exécute sur le grand boîtier, je ne perds pas ce temps s'il est incorrect. Ou même juste le script avec lequel vous l'avez calculé.
Maltysen
@Maltysen J'ai ajouté un exemple 240x140. Heureusement, c'est assez petit
Downgoat
Faut-il toujours arrondir? Dans le premier exemple, le 95.6..., que vous avez arrondi à 95dans la sortie spécifiée.
Dennis
4
PS Il est inutile de poster une question dans le bac à sable à moins que vous ne la laissiez là pendant au moins 24 heures, afin que les gens dans d'autres fuseaux horaires puissent la voir, et en réalité vous devez lui donner 72 heures car tout le monde ne vérifie pas le bac à sable obsessionnellement.
Peter Taylor

Réponses:

19

Pyth - 23 22 19 18 16 octets

Transpose pour obtenir tous les canaux, puis additionne, divise et hexifie chacun. Termine en concaténant et en préfixant a #.

+\#sm.H/sdldCs'z

Prend un nom de fichier image (de tout type) de stdin et le renvoie vers stdout. TRÈS LENT .

+               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

Exemple d'exécution

>>>pyth avg.pyth 
V5VAR.jpg
#8b7d41
Maltysen
la source
Vous souhaiterez peut-être spécifier le type d'image, le cas échéant.
isaacg
1
@isaacg bon point. Ça prend n'importe quoi.
Maltysen
Comment cela prend-il quelque chose, décode-t-il le jpeg en bitmap?
Alec Teal du
3
@AlecTeal Selon la documentation, Pyth vérifie si le fichier est une image et le convertit automatiquement en bitmap. En cherchant dans le référentiel GitHub, il semble qu'il utilise la PILbibliothèque pour gérer les images. Recherchez ici la source exacte.
Bakuriu
@Bakuriu - Je n'ai pas voté pour cette réponse parce que je ne savais pas comment Pyth gérait les images, donc ça me paraissait un peu louche ... mais maintenant que vous y avez donné un aperçu, cela obtient mon vote. Merci pour la clarification!
rayryeng
22

Bash, 46 octets

ImageMagick redimensionne l'image à un pixel qui contient la moyenne des couleurs de l'image, puis la renvoie sous forme de texte.

convert $1 -scale 1x1\! txt:-|egrep -o '#\w+'
SteelRaven
la source
4
C'est intelligent! +1
Maltysen
10

MATLAB - 68 octets

L'image est lue avec imreadcombinée avec uigetfilepour ouvrir une interface graphique pour choisir l'image que vous souhaitez charger. L'hypothèse avec ce code est que toutes les images sont RVB, et pour calculer la couleur moyenne, nous additionnons individuellement sur chaque canal puis divisons par autant d'éléments qu'il y en a dans un canal, ce qui correspond au nombre total de pixels dans l'image RVB ( ) divisé par 3. Étant donné que la moyenne peut éventuellement générer des valeurs à virgule flottante, un appel à est requis pour arrondir le nombre à zéro . combiné avec la chaîne de formatage hexadécimal ( ) est utilisé pour imprimer chaque valeur entière dans la moyenne dans son équivalent hexadécimal. Cependant, le est là pour garantir qu'un 0 supplémentaire est rempli vers la gauche si la valeur moyenne d'un canal est inférieure à 16.numel(I)fixsprintf%x02* .

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

Exemples de cycles

Ce qui est bien, imreadc'est que vous pouvez lire des images directement à partir des URL. À titre d'exemple reproductible, supposons que vous ayez téléchargé les images sur votre ordinateur et exécuté le code ci-dessus ... mais pour démonstration, je vais lire les images directement à partir de Code Golf:

Première image

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

ans =

#53715f

Deuxième image

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

ans =

#8b7d41

* Remarque: Il s'agit d'un effort de collaboration réalisé par les utilisateurs de StackOverflow sur la salle de chat MATLAB et Octave .

rayryeng - Réintégrer Monica
la source
7

CJam, 27 octets

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

Cela a lu une image PPM de STDIN.

CJam n'a pas de traitement d'image intégré, donc ce code attend un PixMap portable ASCII (nombre magique P3) avec une palette complète de 24 bits (valeur maximale 255) et aucun commentaire.

Essai

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

Comment ça marche

'#     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
la source
7

HTML5 + JavaScript (ES6), 335 octets

Ça ne va pas gagner mais j'ai quand même eu du plaisir à le faire.

Utilise l' API HTML5 Canvas . L'entrée est l'URL d'une image compatible 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``)}}

Démo

Comme il s'agit d'ES6, il ne fonctionne actuellement que dans Firefox et 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
la source
3
Hé, j'aime que ce soit exécutable directement dans votre réponse parce que c'est HTML + JS :) +1.
rayryeng
Vous ne pouvez pas remplacer new Imagepar Image()?
Ismael Miguel
@IsmaelMiguelTypeError: Constructor Image requires 'new'
rink.attendant.6
Merde. Mais vous pouvez créer W='width'et H='height'utiliser i[H]oui[W]
Ismael Miguel
1
@IsmaelMiguel Qui utilise plus de personnages
rink.attendant.6
6

Python [3] + SciPy, 144 133 121

Charge les données de pixels, additionne pour chaque canal, divise par taille *, formats. Les valeurs sont arrondies vers zéro.

* taille = largeur * hauteur * canaux, ainsi multiplié par 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
la source
1
Pourquoi ne pas utiliser input()pour prendre le chemin? Cela vous fera économiser 20 octets.
Kade
Merci! J'ai réussi à économiser 11 octets cependant.
Trang Oul
Vous avez seulement besoin d' une importation, import scipy. Remplacez m.imreadpar misc.imread.
Kade
Ne fonctionne pas sans importer divers, NameError: name 'misc' is not defined. Essayé from scipy import*, ne fonctionne pas non plus.
Trang Oul
2
@TrangOul Qu'en est-il from scipy import sum, misc as m? Vous économisez également lorsque vous utilisez sum.
matsjoyce
3

R, 90 octets

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

Le chemin vers le fichier PNG est lu depuis STDIN. Le package pngdoit être installé.

Pas à pas:

#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
la source
2

C, 259 octets

Prend un fichier PPM sans commentaires .

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

Processus

Code initial:

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

Couper les variables et supprimer la boucle:

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

De là, j'ai combiné les différentes déclarations en une seule déclaration de retour. Supprimé et toutes les autres informations de type superflues, renommé les variables et coupé l'espace.

LambdaBeta
la source
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('')
Οurous
la source
2

Java, 449 447 446 430 426 octets

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

Merci à cette réponse sur débordement de pile pour l' String.formatastuce.

SuperJedi224
la source