冬のシーズンに向けて氷のようなアバター画像を作成する


29

冬になり、寒くなり始めます(そして、奇妙なカラフルな帽子が現れ始めます...すぐに)。テーマに合うように、アバターの写真やその他の画像をフリーズさせるコードを書きましょう!

入力

このチャレンジへの提出への入力は、画像(フリーズする画像)と数字(後述のしきい値)である必要があります。

言語でサポートされている方法(引数としてのファイルパスまたはURL、クリップボードからの取得、画像のドラッグアンドドロップなど)およびRGBで色を表現するここにリストされている形式で画像を入力できます(代わりにRGBAをサポート/要求できますが、これは必須ではありません)。

プログラムにハードコーディングすることを除き(コマンドライン引数、STDIN、入力ダイアログなど)、任意の方法で番号を入力することができます(例n=10)。画像にファイルパス/ URLを使用する場合は、この方法でも入力する必要があります。

出力

プログラムは、以下の説明に従って画像を処理し、任意の方法で出力する必要があります(ファイルに出力する、画面に表示する、クリップボードに配置するなど)。

説明

送信では、次の3つの手順で画像を処理する必要があります。nあなたのプログラムが画像とともに入力として受け取った番号を指します。

  1. n各ピクセルのR、G、Bの値を、マンハッタンnピクセル距離内にあるすべてのピクセルの平均R、G、Bの値に置き換えて、範囲外の座標をすべて無視することにより、入力画像に半径のぼかしを適用します。(つまり、Xの差とYの差の合計がより小さいか等しいすべてのピクセルn。)

    (注:便利な組み込み関数があるため、上の画像にはガウスぼかしを使用しました。そのため、画像が少し異なって見える場合があります。)

  2. 各ピクセルをピクセルの距離内のランダムなピクセルに設定しますn/2(「距離」は前のステップと同じ方法で定義されます)。

    これは、画像をループし、各ピクセルをこの範囲内のランダムなピクセルに設定することで行う必要があります。そのため、一部のピクセルが完全に消えたり、一部が重複したりする場合があります。

    すべての変更を同時に適用する必要があります。つまり、ピクセルの古い値(ステップ1の後、このステップの前)を使用し、ランダムピクセルに設定した後の新しい値は使用しません。

  3. 各ピクセルの「青」RGB値に1.5を乗算し、255(またはピクセルのバンドの最大値)に制限して、切り捨てます。

ルール

  • 言語に組み込まれている画像ライブラリ/画像処理関連の機能を使用できます。ただし、説明に記載されている3つの主要なタスクのいずれかを実行する機能は使用できません。たとえば、blur関数を使用することはできませんが、getPixel関数は問題ありません。

  • これはなので、バイト単位の最短コードが勝ちです!


1
ステップ1には、明確にする必要がある2つのポイントがあります。まず、どのメトリックですか?あなたはマンハッタン(L-1)と言い、L-無限を記述します。第二に、画像の境界をどのように処理する必要があります:ラッピングなし、分母を境界内のピクセルのみで平均するように削減しますか?ステップ2には、明確にする必要がある1つのポイントがあります。ステップ1の後のイメージのコピーからのサンプリングか、ステップ2の初期からの変更が伝播できるかです。ステップ3では、255でのキャッピングは24ビットカラーモデルでのみ適切であり、質問はそれを必要としません。
ピーターテイラー14

@PeterTaylor最初の点を除いて、これらすべての点を明確にしようとしました。私はあなたが何を言っているのか本当に理解していません。dx <= n && dy <= nマンハッタン距離の正確な表現ですか?
ドアノブ

いいえ、マンハッタン距離は| dx |です + | dy | <= n。
ピーターテイラー14

@PeterTaylor申し分なく、ありがとう、私もそれを修正しました。
ドアノブ

1
@stokastic「n / 2ピクセルの距離内」は、n / 2をまったく丸めたり、床にしたりすることなく、完全に有効なステートメントであると思います(とても効果的に、「床」であると思います)。
マーティンエンダー14

回答:


14

Python 2-326339358

ユーザーからの入力を受け取ります。最初にファイル、次に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')

これはおそらくもっとゴルフができるかもしれません。

サンプル入力:(Windows)

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

編集:青が伝播されていたバグが修正されました(n = 20のMartinはもはや川ではありません; _;)

n = 2のマーティン:

ここに画像の説明を入力してください

n = 10のマーティン:

ここに画像の説明を入力してください

n = 20のマーティン:

ここに画像の説明を入力してください


3

Python 2-617バイト

編集:いくつかのゴルフ、FryAmTheEggManが私を打たせているように見える:)

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バイト

ええ、私はこれよりもっとうまくできると思った...

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

n = 5のマーティン:

ここに画像の説明を入力してください

n = 20:

ここに画像の説明を入力してください

私と10:

ここに画像の説明を入力してください


何かjavaを実行してからしばらく経ちましたが、できませんでしたk&0xFF00か?さらに、255代わりに使用できません0xFFか?
FryAmTheEggman 14

3

C、429(定義フラグの場合は391 + 38)

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

入力形式:pamヘッダーにコメントまたは余分な空白がないファイル、STDIN経由で渡されるコンテンツ。

n 引数が必要です(何でもかまいません)。

出力形式:pamSTDOUTのファイル。

コンパイルします:

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,33554432スタックサイズを増やします。これは、処理中の画像のサイズに応じて変更または削除できます(プログラムでは、ピクセル数の2倍に4を超えるスタックサイズが必要です)。

-funsigned-charforのunsigned char代わりにgccを使用signed charcharます。C標準ではこれらのオプションのいずれかが許可されており、gccはsigned charデフォルトで使用するため、このオプションはここでのみ必要です。

実行するには(n = 5):

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

注: Windowsでコンパイルする場合stdio.hfcntl.hおよびをio.h含める必要がありmain()、プログラムがテキストではなくバイナリストリームとしてSTDIN / STDOUTを読み書きするために、次のコードをstartに追加する(これはLinuxでは無関係ですが、 Windowsはテキストストリームの\r\n代わりに使用し\nます)。

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

コメント版

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

n = 10のマーティン:

n = 10のマーティン

n = 20のマーティン:

n = 20のマーティン

n = 100のマーティン:

n = 100のマーティン


1

R、440文字

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

読みやすくするために改行あり:

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

サンプル入力: f(2,"avatar.png")

n = 2の結果

n = 2の私のアバター

... n = 10で

n = 10で

... n = 20で

n = 20で

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