为冬季创建冰冷的头像图像


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-无穷大。其次,应该如何处理图像边界:不包裹,将分母减少到仅边界内像素的平均值?步骤2有一点需要澄清:步骤1之后的图像副本中的采样是可以传播的,还是可以传播步骤2初期的更改?对于第3步,上限为255仅适用于24位颜色模型,并且该问题在任何地方都不需要。
彼得·泰勒

@PeterTaylor我试图阐明所有这些要点,除了第一个要点。我真的不明白你在说什么;dx <= n && dy <= n是曼哈顿距离的精确表示,不是吗?
门把手

不,曼哈顿的距离是| dx | + | dy | <= n。
彼得·泰勒

@PeterTaylor好吧,谢谢,我也已修复此问题。
门把手

1
@stokastic我认为“在n / 2像素的距离内”是一个完全有效的语句,根本不需要四舍五入为n / 2(我认为很有效,为“ floored”)。
Martin Ender 2014年

Answers:


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')

:P多亏@ SP3000提出高尔夫方面的建议!

输入样例:(Windows)

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

编辑:修复了正在传播蓝色的错误(n = 20的马丁不再是河; _;)

马丁(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 2014年

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-char使用gcc unsigned char代替signed charfor char。C标准允许使用这些选项中的任何一个,并且仅在此处需要此选项,因为signed char默认情况下gcc使用。

要运行(n = 5):

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

注:如果在Windows上编译,stdio.hfcntl.hio.h必须被包括在内,并添加到开始下面的代码main(),以使程序读取/写入标准输入/输出为二进制,而不是文本,流(这是在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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.