Створюйте крижані аватарські зображення для зимового сезону


29

Настала зима, і настала пора року, коли вона почне холодно (а для дивних барвистих головних уборів почати з’являтися… незабаром). Давайте напишемо якийсь код, щоб зробити зображення аватара та інші зображення замороженими, щоб відповідати темі!

Вхідні дані

Вхідними даними для цього виклику повинні бути зображення (зображення, яке потрібно зробити замороженим) та число (поріг, який буде пояснено пізніше).

Ви можете вводити зображення будь-яким способом, який підтримує їх мова (шлях до файлу або URL-адреса як аргумент, беручи його з буфера обміну, перетягуючи та відпускаючи зображення тощо), і в будь-якому перерахованому тут форматі, що виражає кольори в RGB (ви Ви можете підтримувати / вимагати натомість RGBA, якщо хочете, але це не є вимогою).

Ви можете ввести номер будь-яким способом, який ви також хотіли (аргумент командного рядка, STDIN, діалогове вікно введення тощо), за винятком жорсткого кодування його у вашій програмі (наприклад n=10). Якщо ви використовуєте шлях / URL-адресу для зображення, його також слід вводити таким чином.

Вихід

Програма повинна обробити зображення відповідно до наведеного нижче опису, а потім вивести його будь-яким способом (до файлу, показуючи його на екрані, поміщаючи в буфер обміну тощо).

Опис

Подання повинні обробити зображення з наступними трьома кроками. nпозначає число, яке ваша програма отримала як вхід разом із зображенням.

  1. Застосувати розмиття радіусу nдо вхідного зображення, замінивши R кожного пікселя, G, і значення B із середнім R, G, і значенням B всіх пікселів в межах Manhattan відстані від 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 взагалі (так ефективно, "я думаю").
Мартін Ендер

Відповіді:


14

Пітон 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

Редагувати : помилка виправлена ​​там, де розповсюджувався синій (Мартін з n = 20 - це вже не річка; _;)

Мартін з n = 2:

введіть тут опис зображення

Мартін з n = 10:

введіть тут опис зображення

Мартін з n = 20:

введіть тут опис зображення


3

Пітон 2 - 617 байт

EDIT: гольф дещо, схоже на 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 charfor char. Стандарти C дозволяють використовувати будь-який із цих варіантів, і цей варіант потрібен лише тут, оскільки використовує gccsigned 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

Мартін з 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.