黒と白の虹


60

黒と白のピクセルと(x、y)の位置のみが白のピクセルである画像が与えられた場合、他の白のピクセルの走査のみを含むパス内の(x、y)からの最小マンハッタン距離に基づいて白のピクセルに色を付けます。

色付きピクセルの色相は(x、y)からの距離に比例する必要があるため、(x、y)のピクセルは0°(純粋な赤)の色相を持ち、(x、y)から最も遠いピクセルになります。 360°の色相(赤)を持ち、他の色相はシームレスに直線的にブレンドされます。飽和及び値は、両方の100%でなければなりません。

白のピクセルが他の白のピクセルを介して(x、y)に接続されていない場合、白のままにする必要があります。

詳細

  • 入力は、画像または生の画像データのファイル名に加えて、xおよびy整数で構成されます。
  • 出力画像は、一般的な画像ファイル形式でファイルに保存するか、rawでstdoutにパイプするか、単に表示することができます。
  • x値は左端のピクセルで0で、右に行くほど増加します。y値は最上部のピクセルで0で、下に向かって増加します。(x、y)は常に画像の境界内にあります。
  • 完全なプログラムと機能の両方が許可されます。

バイト単位の最短コードが優先されます。

これらの画像はすべて、スペースを節約するために縮小されています。それらをクリックしてフルサイズで表示します。

入力画像:

例1の入力

(x,y) = (165,155) そして (x,y) = (0,0)

例1出力A 例1出力B


入力画像と出力(x,y) = (0,0)

例5の入力 例5入力A


入力画像と出力(x,y) = (600,350)

例2の入力 例2の出力


入力画像と出力(x,y) = (0,0)

例3の入力 例3の出力


入力画像と出力(x,y) = (0,0)

例4の入力 例4の出力


オプションの-30%ボーナス:ユークリッド距離を使用します。アルゴリズムの提案は次のとおりです(概要):

  1. 開始ピクセルがあります。
  2. そのピクセルからの塗りつぶし。
  3. 塗りつぶしで到達したすべてのピクセルに対して、
  4. 開始ピクセルからそのピクセルまで、半単位のステップで直線で移動します。
  5. 各ステップでint()、x座標とy座標に適用します。これらの座標のピクセルが黒の場合、停止します。それ以外の場合は続行します。(これは、見通し方法です。)
  6. 白いピクセルおよび/または以前に非常に長い距離(つまり+10)でラベル付けされたピクセルに接する到達ピクセルは、開始ピクセルになります。

よりメタ的な意味では、このアルゴリズムは、開始/既に色付けされたピクセルから直線で到達可能なすべてのピクセルに広がり、エッジの周りに「インチ」になります。「著しく高い距離」ビットは、アルゴリズムを高速化することを目的としています。正直なところ、ユークリッド距離をどのように実装するかは問題ではなく、このように見える必要があります。

これは、上記のアルゴリズムを使用したユークリッド距離での最初の例のようです。

入力画像と (x,y) = (165,155)

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


Calvin'sHobbiesとtrichoplaxに、このチャレンジを書くのを手伝ってくれてありがとう!楽しんで!


7
私はゴルフをするつもりはありませんが、画像の上にマウスを乗せると色が即座に更新できるJavascriptバージョンを作成しました。ここでのテスト画像は、私のような小さい画像しようとお勧めするので、それは速く走るには大きすぎますこのまたはこれを
カルビンの趣味

これはすごい!ゴルフバージョンの良いベースになるにはあまりにも効率的だと
思う

2
迷路は、このように色付けされていると簡単に解決できます!
mbomb007

最後の例は本当に美しいです。入力画像は単なるノイズですか?
ディルナン

@dylnan:ボーナスの直前の例について話しているなら、それは実際には迷路です。クリックすると、フルサイズで表示できます。
エレンディアスターマン

回答:


33

Matlab、255 245 231バイト

これは、最初にイメージ名を、次にyを期待しますx

I=@input;i=imread(I('','s'));[r,c]=size(i);m=zeros(r,c);m(I(''),I(''))=1;M=m;d=m;K=[1,2,1];for k=1:r*c;d(m&~M)=k;M=m;m=~~conv2(m,K'*K>1,'s');m(~i)=0;end;z=max(d(:));v=[1,1,3];imshow(ind2rgb(d,hsv(z)).*repmat(m,v)+repmat(~d&i,v),[])

シードピクセルが1に設定されたマスクを作成し、距離アキュムレーター(画像のサイズの両方)を使用して、大まかに塗りつぶし(または、必要に応じて「4近傍のダイクストラ」)を実装し、次に以下を繰り返します手順:

  • 4近傍カーネルでマスクを畳み込みます(これは非常に非効率的な部分です)
  • マスクのすべての非ゼロピクセルを1に設定します
  • 画像のすべての黒ピクセルをゼロに設定します
  • このステップでマスクが変更されたアキュムレータのすべての値を k
  • 増加する k
  • マスクに変更がなくなるまで繰り返します(実際にはこの条件をチェックしませんが、画像のピクセル数を上限として使用します。これは通常非常に悪い上限ですが、これはcodegolf =です)

これにより、距離アキュムレータのすべてのピクセルからシードピクセルまでのマンハッタン距離が残ります。次に、指定された色の範囲をたどって新しいイメージを作成し、「最初の」色相を値0に、「最後の」色相を最大距離にマッピングします。

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

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

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

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

おまけとして、ここに距離がどのように計算されるかのきれいな写真があります。明るい=遠く。

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


3
これは、娘が描くために印刷したいものです。
rayryeng-モニカの復元15年

@rayryengテンプレートはEl'endia Starmanの作品であり、私のものではありません=)
flawr

あなたはまだ画像に色を付けます:D。最後のステップを実行しました。
rayryeng-モニカの復元15年

4
私が感銘を受けた。チャレンジをほとんど理解できなかったlol
zfrisch

正直なところ、私が使用したいのは、風景を作成することです。
corsiKa

3

ブリッツ2D / 3D、3068 * 0.7 = 2147.6

これは、ゴルフのユークリッドアルゴリズムのリファレンス実装です。

image=LoadImage("HueEverywhere_example1.png")
Graphics ImageWidth(image),ImageHeight(image)
image=LoadImage("HueEverywhere_example1.png")
x=0
y=0
w=ImageWidth(image)
h=ImageHeight(image)
Type start
Field x,y
Field dis#
Field nex.start
End Type
Type cell
Field x,y
Field dis#
End Type
Type oldCell
Field x,y
Field dis#
End Type
initCell.start=New start
initCell\x=x
initCell\y=y
initCell\dis=1
Dim array#(w,h)
imgBuff=ImageBuffer(image)
LockBuffer(imgBuff)
s.start=First start
colr=col(0,0,0)
colg=col(0,0,1)
colb=col(0,0,2)
newcol=colr*256*256+colg*256+colb
WritePixelFast(s\x,s\y,newcol,imgBuff)
While s<>Null
c.cell=New cell
c\x=s\x
c\y=s\y
c\dis=s\dis
While c<>Null
For dy=-1To 1
For dx=-1To 1
If dx*dy=0And dx+dy<>0
nx=c\x+dx
ny=c\y+dy
ndis#=s\dis+Sqr#((nx-s\x)*(nx-s\x)+(ny-s\y)*(ny-s\y))
If nx >= 0And nx<w And ny >= 0And ny<h
If KeyHit(1)End
pixcol=ReadPixelFast(nx,ny,imgBuff)
If pixcol<>-16777216
If array(nx,ny)=0Or ndis<array(nx,ny)
check=1
steps=Ceil(dis)*2
For k=0 To steps
r#=k*1./steps
offx#=Int(s\x+(c\x-s\x)*r)
offy#=Int(s\y+(c\y-s\y)*r)
pixcol2=ReadPixelFast(offx,offy,imgBuff)
If pixcol2=-16777216
check=0
Exit
EndIf
Next
If check
array(nx,ny)=ndis
newCell.cell=New cell
newCell\x=nx
newCell\y=ny
newCell\dis=ndis
EndIf
EndIf
EndIf
EndIf
EndIf
Next
Next
o.oldCell=New oldCell
o\x=c\x
o\y=c\y
o\dis=c\dis
Delete c
c=First cell
Wend
For o.oldCell=Each oldCell
bordersWhite=0
For dy=-1To 1
For dx=-1To 1
If dx<>0Or dy<>0
nx=o\x+dx
ny=o\y+dy
If nx>=0And nx<w And ny>=0And ny<h
pixcol=ReadPixelFast(nx,ny,imgBuff)
If (pixcol=-1And array(nx,ny)=0)Or array(nx,ny)>o\dis+9
bordersWhite=1
Exit
EndIf
EndIf
EndIf
Next
If bordersWhite Exit
Next
If bordersWhite
ns.start=New start
ns\x=o\x
ns\y=o\y
ns\dis=o\dis
s2.start=First start
While s2\nex<>Null
If ns\dis<s2\nex\dis
Exit
EndIf
s2=s2\nex
Wend
ns\nex=s2\nex
s2\nex=ns
EndIf
Delete o
Next
EndIf
s2=s
s=s\nex
Delete s2
Wend
maxDis=0
For j=0To h
For i=0To w
If array(i,j)>maxDis maxDis=array(i,j)
Next
Next
For j=0To h
For i=0To w
dis2#=array(i,j)*360./maxDis
If array(i,j) <> 0
colr=col(dis2,0,0)
colg=col(dis2,0,1)
colb=col(dis2,0,2)
newcol=colr*256*256+colg*256+colb
WritePixelFast(i,j,newcol,imgBuff)
EndIf
Next
Next
UnlockBuffer(imgBuff)
DrawImage image,0,0
Function col(ang1#,ang2#,kind)
While ang1>360
ang1=ang1-360
Wend
While ang1<0 
ang1=ang1+360
Wend
While ang2>180
ang2=ang2-360
Wend
While ang2<-180
ang2=ang2+360
Wend
a3#=ang2/180.
If ang1>300
diff#=(ang1-300)/60.
r=255
g=0
b=255*(1-diff)
ElseIf ang1>240
diff#=(ang1-240)/60.
r=255*diff
g=0
b=255
ElseIf ang1>180
diff#=(ang1-180)/60.
r=0
g=255*(1-diff)
b=255
ElseIf ang1>120
diff#=(ang1-120)/60.
r=0
g=255
b=255*diff
ElseIf ang1>60
diff#=(ang1-60)/60.
r=255*(1-diff)
g=255
b=0
Else
diff#=(ang1-00)/60.
r=255
g=255*diff
b=0
EndIf
If a3>0
r2=r+a3*(255-r)
g2=g+a3*(255-g)
b2=b+a3*(255-b)
Else
r2=r+a3*r
g2=g+a3*g
b2=b+a3*b
EndIf
If r2>255
r2=255
ElseIf r2<0
r2=0
EndIf
If g2>255
g2=255
ElseIf g2<0
g2=0
EndIf
If b2>255
b2=255
ElseIf b2<0
b2=0
EndIf
If kind=0
Return r2
ElseIf kind=1
Return g2
ElseIf kind=2
Return b2
Else
Return 0
EndIf
End Function

実際、これがオリジナルと比較してどれだけ読めないか嫌いです。(ちなみに、これは5305バイトです。)実際、すべてに1文字の変数名を使用することで、さらに多くのバイトを切り捨てることができますが、これは既にとんでもないことです。そして、すぐに勝つことはありません。:P


2

C ++ / SFML:1271 1235 1226バイト

user202729による-36バイトのおかげZacharýによる-9バイトのおかげ

#include<SFML\Graphics.hpp>
#include<iostream>
#define V std::vector
#define P e.push_back
#define G(d,a,b,c) case d:return C(a,b,c);
#define FI(r,s)(std::find_if(e.begin(),e.end(),[&a](const T&b){return b==T{a.x+(r),a.y+(s),0};})!=e.end())
using namespace sf;using C=Color;struct T{int x,y,c;bool operator==(const T&a)const{return x==a.x&&y==a.y;}};int max(V<V<int>>&v){int m=INT_MIN;for(auto&a:v)for(auto&b:a)m=b>m?b:m;return m;}C hsv2rgb(int t){int ti=t/60%6;float f=t/60.f-ti,m=(1.f-f)*255,n=f*255;switch(ti){G(0,255,n,0)G(1,m,255,0)G(2,0,255,n)G(3,0,m,255)G(4,n,0,255)G(5,255,0,m)default:throw std::exception();}}void r(Image&a,int x,int y){auto d=a.getSize();V<V<int>>m(d.x,V<int>(d.y));int i=0,j,c=0,t;for(;i<d.y;++i)for(j=0;j<d.x;++j)m[j][i]=a.getPixel(j,i)==C::Black?-1:0;V<T>e{{x,y,1}};while(e.size()){V<T>t=std::move(e);for(auto&a:t){m[a.x][a.y]=a.c;if(a.x>0&&m[a.x-1][a.y]==0&&!FI(-1,0))P({a.x-1,a.y,a.c+1});if(a.y>0&&m[a.x][a.y-1]==0&&!FI(0,-1))P({a.x,a.y-1,a.c+1});if(a.x<m.size()-1&&m[a.x+1][a.y]==0&&!FI(1,0))P({a.x+1,a.y,a.c+1});if(a.y<m[0].size()-1&&m[a.x][a.y+1]==0&&!FI(0,1))P({a.x,a.y+1,a.c+1});}}c=max(m)-1;for(i=0,j;i<d.y;++i)for(j=0;j<d.x;++j)if(m[j][i]>0)a.setPixel(j,i,hsv2rgb(360.f*(m[j][i]-1)/c));}

sf::Imageパラメータはまた、出力(変更される)です。次のように使用できます。

sf::Image img;
if (!img.loadFromFile(image_filename))
    return -1;

r(img, 0, 0);

if (!img.saveToFile(a_new_image_filename))
    return -2;

最初のパラメーターは画像入力(および出力)であり、2番目と3番目のパラメーターは開始する必要があるxand yパラメーターです


スイッチケースも``である...おそらくマクロ定義が有用であろうという無駄なようだsetPixel(j, i,hsv2し、FI(xm,ym) (std::find_if本当に必要?
user202729

G(d,a,b,c)との間のスペースを削除できcase d:ます。また、間のスペースcase d:とは、return C(a,b,c)同様に不要です。(b>m?b:m)括弧を必要とせず、操作の順番で(t/60)%6=> t/60%6を使用します。
ザカリー

またxm、おそらく名前を変更しym、より短い変数名に変更する必要があります
ザカリー

私はそれが間のスペースを削除することも可能だと思うG(d,a,b,c)caseFIti、とhsv2rgbそれぞれが短い名前に置き換えることができます。
ザカリー

1

C ++、979 969 898 859 848バイト

#include<cstdio>
#include<cstdlib>
#define K 400
#define L 400
#define M (i*)malloc(sizeof(i))
#define a(C,X,Y)if(C&&b[Y][X].c){t->n=M;t=t->n;b[Y][X].d=d+1;t->n=0;t->c=X;t->d=Y;}
#define A(n,d)case n:d;break;
#define F fgetc(f)
#define W(A,B) for(A=0;A<B;A++){
struct i{int c;int d;int v;i*n;}b[L][K]={0},*h,*t;float m=0;int main(){FILE*f=fopen("d","r+b");int x,y,d=0;W(y,L)W(x,K)b[y][x].c=F<<16|F<<8|F;}}rewind(f);x=165,y=155;h=M;h->c=x;h->d=y;b[y][x].d=d;t=h;while(h){i*p=b[h->d]+h->c;if(p->v)h=h->n;else{p->v=1;x=h->c;y=h->d;d=p->d;m=d>m?d:m;a(x>0,x-1,y)a(x<K-1,x+1,y)a(y>0,x,y-1)a(y<L-1,x,y+1)}}W(y,L)W(x,K)i p=b[y][x];unsigned char n=-1,h=p.d/(m/n),R=h%43*6,Q=n*(n-(n*R>>8))>>8,t=n*(n-(n*(n-R)>>8))>>8,r,g,b;switch(h/43){A(0,n,t,0)A(1,Q,n,0)A(2,0,n,t)A(3,0,Q,n)A(4,t,0,n)A(5,n,0,Q)}d=h?r|g<<8|b<<16:p.c?-1:0;fwrite(&d,1,3,f);}}}
  • 入力:RGBデータファイル(ファイルに含まれる:d)
  • 出力:RGBA RGBデータファイル(ファイルに出力:d)
  • 例:convert -depth 8 -size "400x400" test.png d.rgb && mv -f d.rgb d && g ++ -o test main.c && ./test
  • 注:画像のサイズと開始はソースレベルで制御されます。これが問題である場合は、50バイトか何かを追加してください。

直接的な「ウルフ」ではありませんが、これは私が最初にモックしたCプロトタイプでした。

#include "stdio.h"
#include "stdlib.h"

struct i{
    unsigned int c;
    int d;
    int v;
}b[400][400]={0};

typedef struct q{
    int x;
    int y;
    struct q *n;
}q;
q *qu;
q *t;
float m=0;
int get_dist(int x, int y)
{
    int d = 0;

}

void flood(int x,int y,int d){
    qu=malloc(sizeof(q));
    qu->x=x;qu->y=y;b[y][x].d=d;
    t=qu;
    while(qu){
        struct i *p = &b[qu->y][qu->x];
        if(p->v){qu=qu->n; continue;}
        p->v=1;x=qu->x;y=qu->y;d=p->d;
        #define a(C,X,Y) if(C&&b[Y][X].c){t->n=malloc(sizeof(q));t=t->n;b[Y][X].d=d+1;t->n=0;t->x=X;t->y=Y;}
        a(x>0,x-1,y);
        a(x<399,x+1,y);
        a(y>0,x,y-1);
        a(y<399,x,y+1);
        m=p->d>m?p->d:m;
    }
}

unsigned int C(int h)
{
    int r=0,g=0,b=0;
    int s=255,v=255;
    unsigned char R, qq, t;

    R = h%43*6; 

    qq = (v * (255 - ((s * R) >> 8))) >> 8;
    t = (v * (255 - ((s * (255 - R)) >> 8))) >> 8;

    switch (h / 43){
        case 0: r = v; g = t; break;
        case 1: r = qq; g = v; break;
        case 2: g = v; b = t; break;
        case 3: g = qq; b = v; break;
        case 4: r = t; b = v; break;
        case 5: r = v; b = qq; break;
    }

    return r|(g<<8)|(b<<16)|255<<24;
}

#define F fgetc(f)
int main()
{
    FILE *f=fopen("d", "r+b");
    for(int y=0; y<400; y++){
        for(int x=0; x<400; x++){
            b[y][x].c = (F<<24)|(F<<16)|(F<<8);
        }
    }
    rewind(f);
    flood(165,155,1);
    m/=255.f;
    for(int y=0; y<400; y++){
        for(int x=0; x<400; x++){
            struct i p = b[y][x];
            unsigned int h = C(p.d/m);
            int o = p.c?-1:255<<24;
            if(p.d)fwrite(&h,4,1,f);
            else fwrite(&o,4,1,f);
        }
    }
}

多くの概念は類似していますが、確かに無数の小さな変更があります。これをCとしてコンパイルするには、C11を使用する必要があります(C99はおそらく動作しますが、C11でのみ厳密にテストしました)。
私はこの挑戦をとても楽しんだ。何か新しいことに挑戦するアイデアをくれてありがとう:)。
編集:ゴルフが少し良くなりました。
Edit2:ピクセル構造体とキューが同じになるように2つの構造体をマージし、マクロをさらに酷使し、一連の符号なし文字を定義するときに-1として定義できるように255をリフローし、最後に関数呼び出しを削除しました。
Edit3:いくつかの変数、演算子の優先度の調整、およびアルファチャネルを保存するRGBに変換された出力を
再利用しました。Edit4:これでこれで完了です。ポインター演算の変更とわずかな制御フローの調整。


0

Python 3およびmatplotlib、251バイト

from pylab import*
def f(i,p):
    h,w,_=i.shape;o=full((h,w),inf);q=[p+(0,)]
    while q:
        x,y,d=q.pop(0)
        if w>x>=0and h>y>=0and i[y,x,0]:o[y,x]=d;i[y,x]=0;d+=1;q+=[(x-1,y,d),(x+1,y,d),(x,y-1,d),(x,y+1,d)]
    imshow(i);imshow(o,'hsv')

入力は、matplotlibのimshow()関数によって返されるMxNx3 numpy配列です。入力は関数によって変更されるため、事前にコピーする必要があります。matplotlibが「インタラクティブ」モードの場合、画像を自動的に表示します。そうでない場合はshow()、さらに7バイトの呼び出しを追加する必要があります。

出力は、最初に元の画像を表示し、次にその上に虹の画像を表示することにより作成されます。Matplotlibは、infとnanを透明として扱い、白黒画像が透けて見えるようにします。

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