สร้างภาพอวตารเย็นฉ่ำสำหรับฤดูหนาว


29

มันเป็นฤดูหนาวและเวลาของปีก็เริ่มที่จะเริ่มเย็น (และสำหรับผ้าโพกศีรษะสีสันสดใสเพื่อเริ่มปรากฏ ... เร็ว ๆ นี้) ลองเขียนโค้ดเพื่อทำให้ภาพประจำตัวและภาพอื่น ๆ ตรึงลงเพื่อให้เข้ากับธีม!

อินพุต

อินพุตสำหรับการส่งไปที่ความท้าทายนี้ควรเป็นภาพ (ภาพที่จะทำให้แข็ง) และตัวเลข (เกณฑ์ซึ่งจะอธิบายในภายหลัง)

คุณสามารถใส่รูปภาพในภาษาที่คุณรองรับ (พา ธ ไฟล์หรือ URL เป็นอาร์กิวเมนต์นำมาจากคลิปบอร์ดลากและวางรูปภาพ ฯลฯ ) และในรูปแบบใด ๆ ที่แสดงไว้ที่นี่ซึ่งแสดงสีใน RGB (คุณ สามารถรองรับ / ต้องการ RGBA แทนได้หากคุณต้องการ แต่นี่ไม่ใช่ข้อกำหนด)

คุณสามารถป้อนหมายเลขในแบบที่คุณต้องการได้เช่นกัน (อาร์กิวเมนต์บรรทัดคำสั่ง, STDIN, กล่องโต้ตอบอินพุต ฯลฯ ) ยกเว้นการเข้ารหัสฮาร์ดโค้ดลงในโปรแกรมของคุณ (เช่นn=10) หากคุณใช้เส้นทางของไฟล์ / URL สำหรับภาพจะต้องมีการป้อนข้อมูลในลักษณะนี้เช่นกัน

เอาท์พุต

โปรแกรมจะต้องประมวลผลภาพตามคำอธิบายด้านล่างแล้วส่งออกในลักษณะใด ๆ ที่คุณต้องการ (ไปยังไฟล์ที่แสดงบนหน้าจอวางไว้บนคลิปบอร์ด ฯลฯ )

ลักษณะ

การส่งควรประมวลผลภาพด้วยสามขั้นตอนต่อไปนี้ nหมายถึงหมายเลขที่โปรแกรมของคุณได้รับเป็นอินพุตพร้อมกับรูปภาพ

  1. ใช้รัศมีเบลอnกับภาพที่ป้อนโดยแทนที่ค่า R, G และ B ของแต่ละพิกเซลด้วยค่าเฉลี่ย R, G และ B ของพิกเซลทั้งหมดภายในระยะแมนฮัตตันของnพิกเซลโดยไม่สนใจพิกัดนอกขอบเขตทั้งหมด (เช่นพิกเซลทั้งหมดที่ผลรวมของความแตกต่างใน X และความแตกต่างใน Y น้อยกว่าหรือเท่ากับn)

    (หมายเหตุ: ฉันใช้ภาพเบลอแบบเกาส์สำหรับภาพด้านบนเพราะมีฟังก์ชั่นในตัวเพื่อความสะดวกดังนั้นภาพของคุณอาจดูแตกต่างออกไปเล็กน้อย)

  2. ตั้งค่าแต่ละพิกเซลเป็นพิกเซลสุ่มภายในระยะทางn/2พิกเซล ("ระยะทาง" ถูกกำหนดเช่นเดียวกับในขั้นตอนก่อนหน้า)

    สิ่งนี้ควรทำโดยวนลูปผ่านภาพและตั้งค่าแต่ละพิกเซลเป็นพิกเซลสุ่มในช่วงนี้ดังนั้นบางพิกเซลอาจหายไปทั้งหมดและบางส่วนอาจซ้ำกัน

    การเปลี่ยนแปลงทั้งหมดจะต้องใช้พร้อมกัน กล่าวอีกนัยหนึ่งใช้ค่าเก่าของพิกเซล (หลังขั้นตอนที่ 1 แต่ก่อนหน้าขั้นตอนนี้) ไม่ใช่ค่าใหม่หลังจากตั้งค่าเป็นพิกเซลแบบสุ่ม

  3. คูณค่า RGB "สีน้ำเงิน" ของแต่ละพิกเซล 1.5 เท่ากำหนดที่ 255 (หรือค่าสูงสุดสำหรับวงพิกเซลเท่าไหร่) และปัดเศษลง

กฎระเบียบ

  • คุณสามารถใช้ไลบรารีรูปภาพ / ฟังก์ชั่นที่เกี่ยวข้องกับการประมวลผลภาพที่สร้างขึ้นในภาษาของคุณ อย่างไรก็ตามคุณไม่สามารถใช้ฟังก์ชั่นใด ๆ ที่ดำเนินการหนึ่งในสามภารกิจหลักที่กล่าวถึงในคำอธิบาย ตัวอย่างเช่นคุณไม่สามารถใช้blurฟังก์ชั่นได้ แต่getPixelฟังก์ชั่นใช้ได้

  • นี่คือดังนั้นโค้ดที่สั้นที่สุดในหน่วยไบต์ชนะ!


1
ขั้นตอนที่ 1 มีสองจุดที่ต้องชี้แจง ประการแรกการวัดไหน? คุณพูดแมนฮัตตัน (L-1) และอธิบาย L-infinity ประการที่สองวิธีจัดการขอบเขตของภาพ: ไม่มีการตัดและลดส่วนที่เป็นค่าเฉลี่ยมากกว่าพิกเซลภายในขอบเขต ขั้นตอนที่ 2 มีจุดหนึ่งที่ต้องการความกระจ่าง: การสุ่มตัวอย่างจากสำเนาของภาพหลังขั้นตอนที่ 1 หรือสามารถเปลี่ยนแปลงตั้งแต่ต้นในขั้นตอนที่ 2 เผยแพร่หรือไม่ สำหรับขั้นตอนที่ 3 การกำหนดที่ 255 จะเหมาะสมในรูปแบบสี 24 บิตเท่านั้นและคำถามก็ไม่จำเป็นต้องมี
Peter Taylor

@PeterTaylor ฉันพยายามชี้แจงประเด็นทั้งหมดยกเว้นประเด็นแรก ฉันไม่เข้าใจสิ่งที่คุณพูด dx <= n && dy <= nการเป็นตัวแทนของระยะทางแมนฮัตตันที่ถูกต้องเป็นจริงหรือไม่?
ลูกบิดประตู

ไม่ระยะทางแมนฮัตตันคือ | dx | + | dy | <= n
Peter Taylor

@ PeterTaylor เอาล่ะขอบคุณฉันได้แก้ไขเช่นกัน
ลูกบิดประตู

1
@stokastic ฉันคิดว่า "ภายในระยะห่างจาก n / 2 พิกเซล" เป็นคำสั่งที่สมบูรณ์แบบโดยไม่ต้องปัดเศษ / ปูพื้น n / 2 เลย (อย่างมีประสิทธิภาพ "พื้น" ฉันคิดว่า)
Martin Ender

คำตอบ:


14

Python 2 - 326 339 358

รับอินพุตจากผู้ใช้ 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')

นี่อาจเป็นเรื่องที่ต้องตีกอล์ฟอีกมาก: P ขอบคุณ @ SP3000 สำหรับไอเดียการเล่นกอล์ฟ!

ตัวอย่างอินพุต: (Windows)

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

แก้ไข : แก้ไขข้อผิดพลาดที่สีน้ำเงินถูกแพร่กระจาย (Martin ที่มี n = 20 ไม่ใช่แม่น้ำอีกต่อไป; _;)

มาร์ตินกับ n = 2:

ป้อนคำอธิบายรูปภาพที่นี่

มาร์ตินกับ n = 10:

ป้อนคำอธิบายรูปภาพที่นี่

มาร์ตินกับ n = 20:

ป้อนคำอธิบายรูปภาพที่นี่


3

Python 2 - 617 ไบต์

แก้ไข: golfed บางดูเหมือน 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:

ป้อนคำอธิบายรูปภาพที่นี่


เป็นเวลานานแล้วที่ฉันต้องการอะไรจากจาวา แต่ทำk&0xFF00ไม่ได้เหรอ? นอกจากนี้คุณไม่สามารถใช้255แทน0xFF?
FryAmTheEggman

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 จำเป็นต้องมีอาร์กิวเมนต์ (สามารถเป็นอะไรก็ได้)

รูปแบบผลลัพธ์: pamไฟล์ใน STDOUT

เพื่อรวบรวม:

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เพิ่มขนาดสแต็ก สิ่งนี้อาจมีการเปลี่ยนแปลงหรือลบออกขึ้นอยู่กับขนาดของรูปภาพที่กำลังประมวลผล (โปรแกรมต้องการขนาดสแต็กมากกว่าสองเท่าของจำนวนพิกเซลคูณ 4)

-funsigned-charมีการใช้ gcc unsigned charแทนสำหรับsigned char charมาตรฐาน C อนุญาตสำหรับตัวเลือกใดตัวเลือกหนึ่งและจำเป็นต้องใช้ตัวเลือกนี้ที่นี่เนื่องจาก gcc ใช้signed charตามค่าเริ่มต้น

หากต้องการเรียกใช้ (n = 5):

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

หมายเหตุ:หากรวบรวมบน Windows, stdio.h, fcntl.hและio.hจะต้องรวมและรหัสต่อไปนี้เพิ่มไปยังจุดเริ่มต้นของmain()ในการสั่งซื้อสำหรับโปรแกรมในการอ่าน / เขียนไป STDIN / STDOUT เป็นไบนารีข้อความไม่ลำธาร (นี่คือที่ไม่เกี่ยวข้องบน 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

Martin กับ 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.