Erstellen Sie eisige Avatar-Bilder für die Wintersaison


29

Es ist Winter und die Zeit des Jahres ist gekommen, in der es langsam kalt wird (und in Kürze komische bunte Kopftücher auftauchen). Schreiben wir einen Code, um Avatar-Bilder und andere Bilder einzufrieren, damit sie zum Thema passen!

Eingang

Die Eingabe für Einsendungen bei dieser Herausforderung sollte ein Bild (das Bild, das eingefroren werden soll) und eine Zahl (der Schwellenwert, der später erläutert wird) sein.

Sie können das Bild so eingeben, wie es Ihre Sprache unterstützt (Dateipfad oder URL als Argument, Übernahme aus der Zwischenablage, Ziehen und Ablegen eines Bildes usw.) und in jedem hier aufgeführten Format , das Farben in RGB ausdrückt (Sie) kann stattdessen RGBA unterstützen / erfordern, wenn Sie möchten, aber dies ist keine Voraussetzung).

Sie können die Nummer auch wie gewünscht eingeben (Befehlszeilenargument, STDIN, Eingabedialog usw.), mit Ausnahme der Hardcodierung in Ihrem Programm (z. B. n=10). Wenn Sie einen Dateipfad / URL für das Bild verwenden, muss dieser ebenfalls auf diese Weise eingegeben werden.

Ausgabe

Das Programm muss das Bild gemäß der folgenden Beschreibung verarbeiten und es dann wie gewünscht ausgeben (in eine Datei, auf dem Bildschirm anzeigen, in die Zwischenablage kopieren usw.).

Beschreibung

Einreichungen sollten das Bild mit den folgenden drei Schritten verarbeiten. nbezieht sich auf die Nummer, die Ihr Programm als Eingabe zusammen mit dem Bild erhalten hat.

  1. Wenden Sie eine Unschärfe des Radius nauf das Eingabebild an, indem Sie die R-, G- und B-Werte jedes Pixels durch die durchschnittlichen R-, G- und B-Werte aller Pixel innerhalb eines Manhattan-Abstandes von nPixeln ersetzen und alle außerhalb der Grenzen liegenden Koordinaten ignorieren. (Dh alle Pixel, bei denen die Summe der Differenz in X und der Differenz in Y kleiner oder gleich ist n.)

    (Hinweis: Ich habe für die obigen Bilder eine Gaußsche Unschärfe verwendet, da es eine praktische integrierte Funktion gab, sodass Ihre Bilder möglicherweise etwas anders aussehen.)

  2. Stellen Sie jedes Pixel auf ein zufälliges Pixel in einem Abstand von n/2Pixeln ein ("Abstand" wird auf dieselbe Weise wie im vorherigen Schritt definiert).

    Dies sollte durch Durchlaufen des Bildes und Einstellen jedes Pixels auf ein zufälliges Pixel in diesem Bereich erfolgen, sodass einige Pixel möglicherweise vollständig verschwinden und andere dupliziert werden.

    Alle Änderungen müssen gleichzeitig wirksam werden. Verwenden Sie mit anderen Worten die alten Werte der Pixel (nach Schritt 1, aber vor diesem Schritt) und nicht die neuen Werte, nachdem Sie sie auf ein zufälliges Pixel festgelegt haben.

  3. Multiplizieren Sie den "blauen" RGB-Wert jedes Pixels mit 1,5, begrenzen Sie ihn auf 255 (oder auf einen beliebigen Maximalwert für ein Pixelband) und runden Sie ihn ab.

Regeln

  • Sie können in Ihre Sprache integrierte Bildbibliotheken / Bildverarbeitungsfunktionen verwenden. Sie dürfen jedoch keine Funktionen verwenden, die eine der drei in der Beschreibung genannten Hauptaufgaben ausführen. Beispielsweise können Sie keine blurFunktion verwenden, aber eine getPixelFunktion ist in Ordnung.

  • Das ist , also gewinnt der kürzeste Code in Bytes!


1
Schritt 1 hat zwei Punkte, die geklärt werden müssen. Erstens, welche Metrik? Sie sagen Manhattan (L-1) und beschreiben L-Unendlichkeit. Zweitens, wie sollen Bildgrenzen gehandhabt werden: kein Zeilenumbruch, der Nenner wird auf den Durchschnitt nur über Pixel innerhalb der Grenze reduziert? In Schritt 2 gibt es einen Punkt, der geklärt werden muss: Wird nach Schritt 1 eine Kopie des Bildes abgetastet, oder können sich Änderungen von Anfang an in Schritt 2 ausbreiten? Für Schritt 3 ist die Begrenzung auf 255 nur in einem 24-Bit-Farbmodell angemessen, und die Frage erfordert dies nirgendwo.
Peter Taylor

@PeterTaylor Ich habe versucht, alle diese Punkte außer dem ersten zu klären. Ich verstehe nicht wirklich, was du sagst; dx <= n && dy <= nist eine genaue Darstellung der Entfernung von Manhattan, nicht wahr?
Türklinke

Nein, Manhattan-Abstand ist | dx | + | dy | <= n.
Peter Taylor

@PeterTaylor Okay, danke, das habe ich auch behoben.
Türklinke

1
@stokastic Ich denke, "innerhalb eines Abstands von n / 2 Pixeln" ist eine absolut gültige Aussage ohne Rundung / Bodenbelag n / 2 (so effektiv, denke ich, "Bodenbelag").
Martin Ender

Antworten:


14

Python 2 - 326 339 358

Nimmt Eingaben vom Benutzer entgegen. Dann erst Datei n.

from PIL.Image import*;from random import*
a,N=input()
i=open(a)
d=list(i.getdata())
x,y=i.size
R=range(x*y)
m=lambda p,n,r:[p[i]for i in R if abs(n%x-i%x)+abs(n/y-i/y)<=r]
k=d[:]
for p in R:t=map(lambda x:sum(x)/len(x),zip(*m(k,p,N)));d[p]=t[0],t[1],min(255,t[2]*3/2)
i.putdata([choice(m(d,p,N/2))for p in R])
i.save('t.png')

Hier könnte wohl noch viel mehr golfen werden: P Danke an @ SP3000 für die Golfideen!

Beispieleingabe: (Windows)

"C:/Silly/Optimizer/Trix/Are/For/Kids.png",7

Edit : Bug behoben, bei dem Blau propagiert wurde (Martin mit n = 20 ist kein Fluss mehr; _;)

Martin mit n = 2:

Bildbeschreibung hier eingeben

Martin mit n = 10:

Bildbeschreibung hier eingeben

Martin mit n = 20:

Bildbeschreibung hier eingeben


3

Python 2 - 617 Bytes

EDIT: Golf einige, sieht aus wie FryAmTheEggMan hat mich aber geschlagen :)

from PIL import Image
import sys,random
j,i,n=sys.argv
n=int(n)
i=Image.open(i)
w,h=i.size
o=Image.new("RGB",(w,h))
D=list(i.getdata())
D=[D[i*w:i*w+w] for i in range(h)]
O=[]
d=n/2
z=range(-n,n+1)
M=lambda n:[[x,y] for x in z for y in z if abs(x)+abs(y)<=n]
m=M(n)
L=w*h
for i in range(L):
 y,x=i/w,i%w;c=r=g=b=0
 for q in m:
  try:C=D[y+q[1]][x+q[0]];r+=C[0];g+=C[1];b+=C[2];c+=1
  except:pass
 r/=c;g/=c;b/=c
 O.append((r,g,min(b*3/2,255)))
R=lambda:random.randint(-d,d)
for i in range(L):
 x,y=i%w,i/w;u=R();v=R()
 while not(0<x+u<w and 0<y+v<h):u=R();v=R()
 O[y*w+x]=O[(y+v)*w+(x+u)]
o.putdata(O)
o.save("b.png")

3

Java - 1009 Bytes

Ich dachte, ich könnte es besser machen ...

import java.awt.*;import java.io.*;import java.util.*;import javax.imageio.*;class r{public static void main(String[]v)throws Exception{java.awt.image.BufferedImage i=ImageIO.read(new File("y.png"));int n=Byte.valueOf(v[0]),w=i.getWidth(),h=i.getHeight();for(int z=0;z<w*h;z++){int x=z/h,y=z%h,r=0,g=0,b=0,c=0,x2,y2,k;for(x2=x-n;x2<=x+n;x2++){for(y2=y-n;y2<=y+n;y2++){if(Math.abs(x2-x)+Math.abs(y2-y)<=n&&x2>=0&&x2<w&&y2>=0&&y2<h){k=i.getRGB(x2,y2); r+=(k>>16)&0xFF;g+=(k>>8)&0xFF;b+=k&0xFF;c++;}}}i.setRGB(x,y,new Color(r/c,g/c,b/c).getRGB());}int[]t=new int[w*h];for(int z=0;z<h*w;z++){int x=z/h,y=z%h,x2,y2;ArrayList<Integer>e=new ArrayList<>();for(x2=x-n;x2<=x+n;x2++){for(y2=y-n;y2<=y+n;y2++){if(Math.abs(x2-x)+Math.abs(y2-y)<=n/2&&x2>=0&&y2>=0&&x2<w&&y2<h)e.add(i.getRGB(x2,y2));}}int p=e.get((int)(Math.random()*e.size())),b=(int)((p&0xFF)*1.5);t[x*h+y]=new Color((p>>16)&0xFF,(p>>8)&0xFF,b>255?255:b).getRGB();}for(int d=0;d<w*h;d++){i.setRGB(d/h,d%h,t[d]);}ImageIO.write(i,"PNG",new File("n.png"));}}

import java.awt.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
class IceBlur{
    public static void main(String[]v)throws Exception{
        java.awt.image.BufferedImage i=ImageIO.read(new File("blah.png"));
        int n=Byte.valueOf(v[0]),w=i.getWidth(),h=i.getHeight();
        for(int z=0;z<w*h;z++){
            int x=z/h,y=z%h,r=0,g=0,b=0,c=0,x2,y2,k;
            for(x2=x-n;x2<=x+n;x2++){
                for(y2=y-n;y2<=y+n;y2++){
                    if(Math.abs(x2-x)+Math.abs(y2-y)<=n&&x2>=0&&x2<w&&y2>=0&&y2<h){
                        k=i.getRGB(x2,y2);
                        r+=(k>>16)&0xFF;
                        g+=(k>>8)&0xFF;
                        b+=k&0xFF;
                        c++;}}}i.setRGB(x,y,new Color(r/c,g/c,b/c).getRGB());}
        int[]t=new int[w*h];
        for(int z=0;z<h*w;z++){
            int x=z/h,y=z%h,x2,y2;
            ArrayList<Integer>e=new ArrayList<>();
            for(x2=x-n;x2<=x+n;x2++){
                for(y2=y-n;y2<=y+n;y2++){
                    if(Math.abs(x2-x)+Math.abs(y2-y)<=n/2&&x2>=0&&y2>=0&&x2<w&&y2<h)e.add(i.getRGB(x2, y2));}}
            int p=e.get((int)(Math.random()*e.size())),b=(int)((p&0xFF)*1.5);
            t[x*h+y]=new Color((p>>16)&0xFF,(p>>8)&0xFF,b>255?255:b).getRGB();}
        for(int d=0;d<w*h;d++){i.setRGB(d/h, d%h, t[d]);}
        ImageIO.write(i,"PNG",new File("blah2.png"));}}

Martin mit n = 5:

Bildbeschreibung hier eingeben

n = 20:

Bildbeschreibung hier eingeben

Ich mit 10:

Bildbeschreibung hier eingeben


Es ist schon eine Weile her, dass ich irgendetwas javaed habe, aber konntest du es nicht tun k&0xFF00? Darüber hinaus können Sie nicht 255anstelle von verwenden 0xFF?
FryAmTheEggman

3

C, 429 (391 + 38 für die Definition von Flags)

i,R,G,B,q;char*c,t[99];main(r,a,b,k,z,p){scanf("%*[^ ]%d%*6s%d%[^N]%*[^R]R\n",&a,&b,t);int j=a*b,d[j],e[j];F(c=d;c<d+j;*c++=getchar());F(;i<j;e[i++]=X<<24|B/q<<16|G/q<<8|R/q,R=G=B=q=0)F(k=0;k<j;)p=d[k++],D<r&&(++q,R+=p&X,G+=p>>8&X,B+=p>>16&X);F(i=!printf("P7\nWIDTH %d\nHEIGHT %d%sNDHDR\n",a,b,t);i<j;d[i++]=e[k])F(;k=rand()%j,D>r/2;);F(c=d;q<j*4;i=(q%4-2?2:3)*c[q]/2,putchar(i>X?X:i),++q);}

Eingabeformat: pamDatei ohne Kommentare oder zusätzliches Leerzeichen in der Kopfzeile, Inhalt wird über STDIN übergeben.

n Argumente sind erforderlich (sie können alles sein).

Ausgabeformat: pamDatei in STDOUT.

Kompilieren:

gcc -DX=255 -DF=for "-DD=z=abs(k-i),z/b+z%a" -Wl,--stack,33554432 -funsigned-char icyavatars.c -o icyavatars

-Wl,--stack,33554432erhöht die Stapelgröße; Dies kann je nach Größe des zu verarbeitenden Bilds geändert oder entfernt werden (das Programm benötigt eine Stapelgröße, die größer ist als die doppelte Anzahl von Pixel mal 4).

-funsigned-charhat gcc verwendung unsigned charstatt signed charfür char. Der C-Standard erlaubt eine dieser Optionen, und diese Option wird nur hier benötigt, weil gcc signed charstandardmäßig verwendet.

Ausführen (n = 5):

./icyavatars random argument here fourth fifth < image.pam > output.pam

Hinweis: Wenn unter Windows kompilieren stdio.h, fcntl.hund io.hmüssen enthalten sein, und der folgende Code zu Beginn des hinzugefügt , main()damit das Programm zum Lesen / Schreiben zu STDIN / STDOUT als binäre, nicht Text, ströme (dies ist irrelevant auf Linux, aber Windows verwendet \r\nstatt \nfür Textströme).

setmode(fileno(stdin), _O_BINARY);
setmode(fileno(stdout), _O_BINARY);

Kommentierte Version

int i,R,G,B,q;
char *c,t[99];
main(r,a,b,k,z,p){
    // read all of header
    // save a large chunk to t, save width to a, save height to b
    scanf("%*[^ ]%d%*6s%d%[^N]%*[^R]R\n", &a, &b, t);
    // create arrays for holding the pixels
    int j = a * b, d[j], e[j];
    // each pixel is 4 bytes, so we just read byte by byte to the int arrays
    for(c = d; c < d + j; ++c)
        *c=getchar();

    // calculating average rgb
    for(i = 0; i < j; ++i){
        // check every pixel; add r/g/b values to R/G/B if manhattan distance < r-1
        for(k = 0; k < j; ++k){
            // pixel being checked
            p = d[k];
            // manhattan distance
            z = abs(k - i)/b + abs(k - i)%a;
            if(z < r){
                // extract components and add
                ++q;
                R += p & 255;
                G += p >> 8 & 255;
                B += p >> 16 & 255;
            }
        }
        // set pixel in e (not d) to average RGB and 255 alpha
        e[i]= 255<<24 | B/q<<16 | G/q<<8 | R/q;
        // clear temporary variables
        R = G = B = q = 0;      
    }

    // print header
    printf("P7\nWIDTH %d\nHEIGHT %d%sNDHDR\n",a,b,t);
    // choose random pixels
    for(i = 0; i < j; ++i){
        // loop until randomly generated integer represents a pixel that is close enough
        do{
            k = rand() % j;
            // manhattan distance
            z = abs(k - i)/b + abs(k - i)%a;
        }while(z > r/2);
        // set d to the new pixel value
        d[i] = e[k];
    }
    // apply blue scaling and output
    for(c = d, q = 0; q < j * 4; ++q){
        // 3/2 if blue component, 1 otherwise
        i = (q % 4 - 2 ? 2 : 3)*c[q]/2;
        // cap components at 255
        putchar(i > 255 ? 255 : i);
    }
}

Martin mit n = 10:

Martin mit n = 10

Martin mit n = 20:

Martin mit n = 20

Martin mit n = 100:

Martin mit n = 100


1

R, 440 Zeichen

f=function(n,p){a=png::readPNG(p);b=a;N=nrow(a);M=ncol(a);r=row(a[,,1]);c=col(a[,,1]);for(i in 1:N)for(j in 1:M)b[i,j,]=apply(a,3,function(x)mean(x[abs(r-i)+abs(c-j)<=n]));for(i in 1:N)for(j in 1:M){g=which(abs(r-i)+abs(c-j)<=n/2,arr.ind=T);o=sample(1:nrow(g),1);b[i,j,]=b[g[o,1],g[o,2],]};b[,,3]=b[,,3]*1.5;b[b>1]=1;png(w=M,h=N);par(mar=rep(0,4));plot(0,t="n",xli=c(1,M),yli=c(1,N),xaxs="i",yaxs="i",ax=F);rasterImage(b,1,1,M,N);dev.off()}

Mit Zeilenumbrüchen zur besseren Lesbarkeit:

f=function(n,p){
    a=png::readPNG(p) #use readPNG from package png
    b=a
    N=nrow(a)
    M=ncol(a)
    r=row(a[,,1])
    c=col(a[,,1])
    for(i in 1:N){ #braces can be deleted if all is contained in one line
        for(j in 1:M){
            b[i,j,]=apply(a,3,function(x)mean(x[abs(r-i)+abs(c-j)<=n]))
            }
        }
    for(i in 1:N){ #i'm sure this loop could be shortened
        for(j in 1:M){
            g=which(abs(r-i)+abs(c-j)<=n/2,arr.ind=T)
            o=sample(1:nrow(g),1)
            b[i,j,]=b[g[o,1],g[o,2],]
            }
        }
    b[,,3]=b[,,3]*1.5 #readPNG gives RGB values on a [0,1] range, so no need to round
    b[b>1]=1
    png(w=M,h=N)
    par(mar=rep(0,4))
    plot(0,t="n",xli=c(1,M),yli=c(1,N),xaxs="i",yaxs="i",ax=F)
    rasterImage(b,1,1,M,N)
    dev.off()
    }

Beispieleingabe: f(2,"avatar.png")

Ergebnisse mit n = 2

Mein Avatar mit n = 2

... mit n = 10

mit n = 10

... mit n = 20

mit n = 20

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.