겨울 시즌에 얼음 아바타 이미지 만들기


29

겨울이되었고, 계절이 추워지기 시작했습니다 (이상한 화려한 머리 장식용 천이 곧 나타나기 시작했습니다). 테마에 맞게 아바타 사진과 다른 이미지를 고정시키는 코드를 작성해 봅시다!

입력

이 챌린지에 대한 제출에 대한 입력은 이미지 (고정 될 이미지)와 숫자 (임계 값, 나중에 설명) 여야합니다.

언어가 지원하는 방식 (파일 경로 또는 URL을 인수로 사용, 클립 보드에서 가져 오기, 이미지 끌어서 놓기 등)과 RGB로 색상을 표현하는 여기나열된 형식으로 이미지를 입력 할 수 있습니다. 원하는 경우 RGBA를 지원 / 요구 할 수 있지만 필수는 아닙니다).

프로그램에 하드 코딩하는 것 (예 :)을 제외하고 원하는 방식으로 번호를 입력 할 수 있습니다 (명령 줄 인수, STDIN, 입력 대화 상자 등 n=10). 이미지에 파일 경로 / URL을 사용하는 경우이 방법으로도 입력해야합니다.

산출

프로그램은 아래 설명에 따라 이미지를 처리 ​​한 다음 원하는 방식으로 (파일로, 화면에 표시하거나, 클립 보드에 넣는 등) 이미지를 출력해야합니다.

기술

제출은 다음 세 단계로 이미지를 처리해야합니다. n이미지와 함께 입력으로 프로그램에서받은 번호를 나타냅니다.

  1. n각 픽셀의 R, G 및 B 값을 맨해튼 거리n픽셀 내에있는 모든 픽셀의 평균 R, G 및 B 값으로 바꾸고 범위를 벗어난 모든 좌표를 무시 하여 입력 이미지에 반경 흐림을 적용합니다 . (즉, X의 차이와 Y의 차이의 합이보다 작거나 같은 모든 픽셀 n.)

    (참고 : 편리한 내장 기능이있어 위의 이미지에 가우시안 블러를 사용했기 때문에 이미지가 약간 다르게 보일 수 있습니다.)

  2. 픽셀 거리 내에서 각 픽셀을 임의의 픽셀로 설정합니다 n/2( "거리"는 이전 단계와 동일한 방식으로 정의 됨).

    이미지를 반복하고이 범위에서 각 픽셀을 임의의 픽셀로 설정하면 일부 픽셀이 완전히 사라지고 일부는 복제 될 수 있습니다.

    모든 변경 사항이 동시에 적용되어야합니다. 즉, 픽셀의 이전 값 (1 단계 후,이 단계 이전)을 임의의 픽셀로 설정 한 후 새 값을 사용하십시오.

  3. 각 픽셀의 "파란색"RGB 값에 1.5를 곱하여 255 (또는 픽셀 대역의 최대 값이 무엇이든)에 내림하고 내림합니다.

규칙

  • 언어에 내장 된 이미지 라이브러리 / 이미지 처리 관련 기능을 사용할 수 있습니다. 그러나 설명에 언급 된 세 가지 주요 작업 중 하나를 수행하는 기능은 사용할 수 없습니다. 예를 들어, blur함수를 사용할 수 없지만 getPixel함수는 정상입니다.

  • 이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다!


1
1 단계에는 설명이 필요한 두 가지 사항이 있습니다. 첫째, 어떤 측정 항목입니까? 맨하탄 (L-1)이라고 말하고 L- 무한대를 설명합니다. 둘째, 이미지 경계를 어떻게 처리해야합니까 : 줄 바꿈 없음, 분모가 경계 내부의 픽셀에 대해서만 평균을 줄입니까? 2 단계는 명확히해야 할 한 가지 점이 있습니다. 1 단계 이후 이미지의 사본에서 샘플링이 수행됩니까, 아니면 2 단계 초반부터 변경 될 수 있습니까? 3 단계의 경우 255로 제한하는 것은 24 비트 색상 모델에만 적합하며 질문이 필요한 것은 아닙니다.
피터 테일러

@PeterTaylor 첫 번째 점을 제외하고 그 요점을 모두 명확하게하려고했습니다. 나는 당신이 무슨 말을하는지 이해하지 못합니다. dx <= n && dy <= n맨해튼 거리의 정확한 표현입니까?
Doorknob

아니요, 맨해튼 거리는 | dx |입니다. + | dy | <= n.
피터 테일러

@PeterTaylor 좋아, 고마워, 나는 그것을 고쳤다.
Doorknob

1
@stokastic "n / 2 픽셀 거리 이내"는 n / 2를 반올림 / 플로어링하지 않고 완벽하게 유효한 명령문이라고 생각합니다 (따라서 "floored"라고 생각합니다).
Martin Ender

답변:


14

파이썬 2-32639358

사용자로부터 입력을받습니다. 다음, 첫 번째 파일 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

편집 : 파란색이 전파되는 버그 수정 (n = 20 인 마틴은 더 이상 강이 아닙니다 ._;)

n = 2 인 마틴 :

여기에 이미지 설명을 입력하십시오

n = 10 인 마틴 :

여기에 이미지 설명을 입력하십시오

n = 20 인 마틴 :

여기에 이미지 설명을 입력하십시오


3

파이썬 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

자바-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 인 Martin :

여기에 이미지 설명을 입력하십시오

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 인수가 필요합니다 (무엇이든 가능).

출력 형식 : 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스택 크기를 증가시킵니다. 처리되는 그림의 크기에 따라 변경되거나 제거 될 수 있습니다 (프로그램은 픽셀 수의 두 배보다 4 배 큰 스택 크기가 필요함).

-funsigned-charfor unsigned char대신 gcc를 사용 합니다 . C 표준은 이러한 옵션 중 하나를 허용하며 gcc 가 기본적으로 사용하기 때문에이 옵션 만 필요합니다 .signed charcharsigned char

실행하려면 (n = 5) :

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

참고 : Windows에서 컴파일하는 경우 stdio.h, fcntl.h그리고 io.h포함되어야하고,의 시작에 추가 된 다음 코드 main()바이너리가 아닌 텍스트, 스트림으로 프로그램의 순서는 STDIN / STDOUT에 읽기 / 쓰기 (이 리눅스에 관련이 있지만, 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.