Kare, Daire, Üçgen,… Dişli?


69

Algodoo ve Paint'i kullanarak bu altı 300 × 300 monokromatik görüntüyü dört uygun şekle yaptım:

Resim 1 Resim 2 Resim 3 Resim 4 Resim 5 Resim 6

Bu görüntü sınıfı aşağıdaki özelliklere sahiptir:

  • Her zaman 300 × 300 piksel, tek renkli (yalnızca siyah beyaz) ve kare, daire, üçgen ve dişliye karşılık gelen tam olarak dört beyaz bölgeye sahipler.
  • Şekiller hiçbir zaman üst üste binmez veya birbirleriyle temas etmez, ayrıca görüntü sınırına dokunmaz veya sınırların dışına çıkar.
  • Şekiller her zaman aynı boyuta sahiptir, ancak herhangi bir şekilde döndürülebilir ve yerleştirilebilirler.

(Şekiller aynı zamanda eşit alanlara sahiptir, ancak bu şekilde raster edildiklerinde piksel sayıları tam olarak eşdeğer değildir.)

Meydan okuma

Böyle bir görüntünün dosya adını alan ve tüm beyaz pikselleri döndüren mümkün olan en kısa programı veya işlevi yazın ...

  • (255, 0, 0)Meydandalarsa kırmızıdır .
  • (0, 0, 255)Dairenin içindeyse mavi .
  • (0, 255, 0)Üçgen içindeyse, yeşildir .
  • (255, 255, 0)viteste ise sarıdır .

Örneğin

Resim 1 renkli

ayrıntılar

Programınız tüm olası giriş görüntülerini etkili bir şekilde çalışmalıdır. (Yalnızca geçerli 300 × 300 tek renkli görüntüler girilir.) Sağladığım altı görüntü yalnızca örneklerdir, çıktılarını programınıza kodlayamayabilirsiniz.

Dahili veya harici bilgisayar görme kütüphanelerini veya işlevlerini kullanamazsınız. Mesele, bunu kendi piksel seviyesindeki işlemlerinizi kullanarak yapmaktır. Görüntüleri açmanıza ve değiştirmenize izin veren resim kütüphanelerini kullanabilirsiniz (örn. Python için PIL).

Renk şemasına bağlı kaldığınız sürece giriş ve çıkış için yaygın olarak kullanılan kayıpsız görüntü dosyası biçimlerini kullanabilirsiniz.

Resim dosya ismini bir fonksiyon argümanı olarak, stdin'den veya komut satırından alabilirsiniz. Çıktı görüntüsü yeni bir dosyaya, aynı dosyaya kaydedilebilir veya yalnızca görüntülenebilir.

puanlama

En az bayt olan gönderim kazanır. Geçerliliklerini belirlemek için başvuruları ek resimlerle test edebilirim.


Girişin kenar yumuşatma olmadan siyah-beyaz olduğunu varsayabilir miyiz? Aksi takdirde, kenar yumuşatma işlevlerini kenar yumuşatma girdilerinden kaldırabilir miyiz?
John Dvorak

@JanDvorak Evet. Tek renkli ile sadece siyah ve beyaz kastediyorum, bu nedenle kenar yumuşatma olamaz.
Calvin'in Hobileri

1
Belirli bir giriş biçimini sadece bir dosya uzantısından daha kesin olarak isteyebilir miyiz? Yani, içeride yorum yapmadan ASCII PBM girişi istiyorum .
John Dvorak

12
Yani ... Bunu çözmeye çalışıyordum ve bu görüntüyle bitirdim . Nasıl olduğundan emin değilim, ama hey, süslü görünüyor. : P
Doorknob

2
Çözümümü Ell'inkiyle aynı fikirde olduğu gibi göndermek istemiyorum ama daha da kötüsü. Ama sadece bunun yapmak için küçük bir zevk olduğunu söylemek istiyorum :)
Chris Burt-Brown

Yanıtlar:


8

J - 246,224 185 bayt

load'viewmat'
(viewmat~0,(255*4 3$_2|.#:3720)/:/:@(<([:}.(>./%+/%#)@:(+/&:*:@(-"1)+/%#)@(4$.$.@:=)&>)<"0@~.@,))@(~.@,i.])@(>./**@{.)@((0,(,-)#:>:i.3)&|.)^:_@(*i.@:$)@(0<readimg_jqtide_)

Bu eğlenceli bir şeydi!

"En büyük odada mıyım?" Yarışması için kullandığım bağlı bileşenler bölümünü tekrar kullandım ve tüm noktaların ortalama ve maksimum mesafe arasındaki oranı her bir bileşenin merkezine kullandım. Hem ölçek hem de rotasyon değişmez olduğu ve verilen şekilleri ayırt edebilecek kadar iyi olduğu için bunun için karar verdim. Bu değeri düşükten yükseğe sıralamak bana renk haritasına izin vermek için kullanılan emir dairesini, dişli, kare ve üçgeni verir.

Viewmap addon'u kullanarak sonucu görüntüler. Dosya okuma ve çıktı dışında alet kutusu kullanılmaz.

Sağlamlık bir gereklilik gibi görünmüyor, bu 18 bayt çıkartıyor. İkame 2 daha gereksiz boşluklar, &.>ile &>de ratiove &.:göre &:başka bir 2 bayt dcent içinde.

Hem kısalmada hem de compkayma cut( ;.) yerine kullanmanın performansında büyük kazanç . Bu şekilde görüntü, 3x3 pencereyle taramak yerine 8 yönde de kopyalanır ve kaydırılır.

idİşlev yapması gerekeni için gülünç karmaşık oldu. Artık görüntüyü benzersiz bir sayılar dizisi ile çarparak, nesneleri BG'ye sıfıra ayarlayarak kimlikleri piksellere atar.

Kod biraz daha açıkladı:

load'viewmat'                                 NB. display only
imnames =: < ;. _2 (0 : 0)
C6IKR.png
DLM3y.png
F1ZDM.png
Oa2O1.png
YZfc6.png
chJFi.png
)

images =: (0<readimg_jqtide_) each imnames    NB. read all images in boxed array

id =: *i.@:$                                  NB. NB. assign one number to each non-background (non-zero) pixel
comp =: (>./ * *@{.)@shift^:_@id              NB. 8 connected neighbor using shift
  shift =: (>,{,~<0 _1 1)&|.                  NB. generate the original, and 8 shifted versions (automatically padding and cropping).
result =: comp each images                    NB. Execute comp verb for each image
col =: (~.@, i. ])                            NB. Color: give each component and BG a separate color.

NB. BG in 0, 0 Get all max distance to center % mean distance to center ratios
ratio  =: (< ([:}.rat@:dcent@getInd &>)  <"0@~.@,)
  getInd =: 4 $. $.@:=                        NB. get indices for component y in array x
  dcent  =: +/&.:*:@(-"1) +/%#                NB. distence from center each point
  rat    =: >./ % +/%#                        NB. ratio from distances

cm=: (255*4 3$_2|.#:3720)                     NB. colormap (except black).
(viewmat~ 0,cm /: /:@ratio )@col each result  NB. for each image, show the result, permuting the colormap according to ratio's

NB. almostgolf this
P1 =: (>./**@{.)@((0,(,-)#:>:i.3)&|.)^:_@(*i.@:$)@(0<readimg_jqtide_) NB. reading till components
P2 =: (<([:}.(>./%+/%#)@:(+/&:*:@(-"1)+/%#)@(4$.$.@:=)&>)<"0@~.@,) NB. recognition: get fraction mean vs max distance to center per component, toss BG.     
P3 =: (viewmat~0,(255*4 3$_2|.#:3720)/:/:@P2)@(~.@,i.])@P1    NB. piece together : permute colormap, display components

NB. seriousgolf
load'viewmat'
f =:(viewmat~0,(255*4 3$_2|.#:3720)/:/:@(<([:}.(>./%+/%#)@:(+/&:*:@(-"1)+/%#)@(4$.$.@:=)&>)<"0@~.@,))@(~.@,i.])@((>./**@{.)@shift^:_)@(*i.@:$)@(0<readimg_jqtide_)
NB. example usage:
f&> imnames NB. do for all images

Bu, ayrıntılı olarak açıklamak için biraz uzun, ama ilgi varsa yapacak.


Sağ üst pikselin bg olması garanti edilmektedir. OP'ye göre "Şekiller asla birbiriyle örtüşmez veya birbirine değmez, görüntü sınırına da dokunmaz veya sınırlardan çıkmaz."
Dr. Belisarius

Teşekkürler, bu yardımcı oldu. (Aslında, ilk piksel, ilk ravelde kaldı demek istedim). Bu, arka plan algılamasını tıraş eder (22 bayt).
jpjacobs

Dramatik uzunluk azaldı ve performansı arttırdı :)
jpjacobs

29

Mathematica, 459 392 bayt

f=(d=ImageData@Import@#/.{a_,_,_}:>a;(For[a={};b={#&@@d~Position~1},b!={},c=#&@@b;b=Rest@b;d[[##&@@c]]=0;a~AppendTo~c;If[Extract[d,c+#]==1,b=b⋃{c+#}]&/@{e={1,0},-e,e={0,1},-e}];m=1.Mean@a;m=#-m&/@a;n=Count[Partition[Norm/@SortBy[m,ArcTan@@#&],300,1,1],l_/;l[[150]]==Max@l];(d[[##&@@#]]=Round[n^.68])&/@a)&/@Range@4;Image[d/.n_Integer:>{{0,0,0},,{0,1,0},{1,0,0},,,,{1,1,0},{0,0,1}}[[n+1]]])&

Ungolfed:

f = (
 d = ImageData@Import@# /. {a_, _, _} :> a;
 (
    For[a = {}; b = {# & @@ d~Position~1},
     b != {},
     c = # & @@ b;
     b = Rest@b;
     d[[## & @@ c]] = 0;
     a~AppendTo~c;
     If[Extract[d, c + #] == 1, 
        b = b ⋃ {c + #}] & /@ {e = {1, 0}, -e, e = {0, 1}, -e}
     ];
    m = 1. Mean@a; m = # - m & /@ a;
    n = 
     Count[Partition[Norm /@ SortBy[m, ArcTan @@ # &], 300, 1, 1], 
      l_ /; l[[150]] == Max@l];
    (d[[## & @@ #]] = Round[n^.68]) & /@ a
    ) & /@ Range@4;
 Image[d /. 
   n_Integer :> {{0, 0, 0}, , {0, 1, 0}, {1, 0, 0}, , , , {1, 1, 
       0}, {0, 0, 1}}[[n + 1]]]
) &

Ben çevirerek 6 daha bayt kurtarabilecek m=1.Mean@a;m=#-m&/@a;içine m=#-Mean@a&/@a;, ama bu ölçüde test için can sıkıcı yürütme zamanı, havaya uçuruyor. (Bunun iki optimizasyon olduğuna dikkat Mean@aedin: döngü dışı hesaplamanın çıkarılması ve kayan nokta sayıları yerine kesin sembolik türlerin kullanılması. İlginçtir ki, kesin türlerin kullanılması , her yinelemede ortalamanın hesaplanmasından çok daha önemlidir.)

Yani bu üç numaralı yaklaşım:

  • Alanlara taşkın doldurma uygulayın.
  • Tüm piksel koordinatlarının ortalaması alınarak her alanın yaklaşık merkezini bulun.
  • Şimdi, şeklin içindeki tüm pikseller için, açıyla o merkeze olan mesafeyi çizelim:

    görüntü tanımını buraya girin

    Üçgen 3 açık maksimaya, kare 4'e, dişli 16'ya ve çemberin sabit yarıçapın etrafındaki takma dalgalanmalarından dolayı tonları vardır.

  • 150Maksimum piksel sayısını 300 piksellik dilimlere bakarak (açı ile sıralanır) buluruz ve konumdaki pikselin maksimum olduğu dilimleri sayarız .
  • Daha sonra tepe noktalarının sayısına bağlı olarak tüm pikselleri renklendiriyoruz (daire 16'dan büyük bir şeydir ve dilimlerin boyutundan dolayı genellikle yaklaşık 20 tepe noktası verir).

Sadece kayıt için, eğer Ell'in fikrini kullanırsam ve bölgeleri herhangi bir piksel ile merkez arasındaki en büyük mesafeye göre sıralarsam, bunu 342 baytta yapabilirim:

f=(d=ImageData@Import@#/.{a_,_,_}:>a;MapIndexed[(d[[##&@@#]]=#&@@#2)&,SortBy[(For[a={};b={#&@@d~Position~1},b!={},c=#&@@b;b=Rest@b;d[[##&@@c]]=0;a~AppendTo~c;If[Extract[d,c+#]==1,b=b⋃{c+#}]&/@{e={1,0},-e,e={0,1},-e}];a)&/@Range@4,(m=Mean@#;Max[1.Norm[#-m]&/@#])&],{2}];Image[d/.n_Integer:>{{0,0,0},{0,0,1},{1,1,0},{1,0,0},{0,1,0}}[[n+1]]])&

Ancak, diğerleri ile rekabet etmek yerine, herkes kendi orijinal algoritmasını kullandığı sürece, bununla rekabet etmeye niyetli değilim.


En ilginç çözüm!
CSharpie

25

Java, 1204 1132 1087 1076

Sadece kendime kanıtlamak için ben bunu yapabilirsiniz.

Fonksiyon bildirimlerinin hemen yanına ithalat dahil ettim; bunun çalışması için sınıfın dışında olması gerekirdi:

import java.awt.*;import java.awt.image.*;import java.io.*;import java.util.*;import javax.imageio.*;

BufferedImage i;Set<Point>Q;void p(String a)throws Exception{i=new BufferedImage(302,302,1);i.getGraphics().drawImage(ImageIO.read(new File(a)),1,1,null);Set<Set<Point>>S=new HashSet<>();for(int y=0;y<300;y++){for(int x=0;x<300;x++){if(!G(x,y)){Point p=new Point(x,y);Q=new HashSet<>();if(!S.stream().anyMatch(s->s.contains(p)))S.add(f(x,y));}}}Object[]o=S.stream().sorted((p,P)->c(p)-c(P)).toArray();s(o[0],255);s(o[1],255<<16);s(o[2],0xFF00);s(o[3],0xFFFF00);ImageIO.write(i.getSubimage(1,1,300,300),"png",new File(a));}boolean G(int x,int y){return i.getRGB(x,y)!=-1;}Set<Point>f(int x,int y){Point p=new Point(x,y);if(!Q.contains(p)&&!G(x,y)){Q.add(p);f(x-1,y);f(x+1,y);f(x,y-1);f(x,y+1);}return Q;}int c(Set<Point>s){return(int)s.stream().filter(p->G(p.x-2,p.y-1)||G(p.x-2,p.y+1)||G(p.x+1,p.y-2)||G(p.x-1,p.y-2)||G(p.x+2,p.y-1)||G(p.x+2,p.y+1)||G(p.x+1,p.y+2)||G(p.x-1,p.y+2)).count();}void s(Object o,int c){((Set<Point>)o).stream().forEach(p->{i.setRGB(p.x,p.y,c);});}

Ungolfed (ve çalıştırılabilir; yani, kazan plakası eklendi):

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.imageio.ImageIO;

public class SquareCircleTriangleGear {
    public static void main(String[]args){
        try {
            new SquareCircleTriangleGear().p("filepath");
        } catch (Exception ex) {
        }
    }
    BufferedImage i;
    Set<Point>Q;
    void p(String a)throws Exception{
        i = new BufferedImage(302,302,BufferedImage.TYPE_INT_RGB);
        i.getGraphics().drawImage(ImageIO.read(new File(a)),1,1,null);
        Set<Set<Point>>set=new HashSet<>();
        for(int y=0;y<300;y++){
            for(int x = 0;x<300;x++){
                if(i.getRGB(x,y)==-1){
                    Point p = new Point(x,y);
                    Q=new HashSet<>();
                    if(!set.stream().anyMatch((s)->s.contains(p))){
                        set.add(fill(x,y));
                    }
                }
            }
        }
        Object[]o=set.stream().sorted((p,P)->c(p)-c(P)).toArray();
        s(o[0],0x0000FF);
        s(o[1],0xFF0000);
        s(o[2],0x00FF00);
        s(o[3],0xFFFF00);
        ImageIO.write(i.getSubImage(1,1,300,300), "png", new File(a));
    }
    Set<Point>fill(int x, int y){
        Point p=new Point(x,y);
        if(!Q.contains(p)&&!i.getRGB(x,y)!=-1) {
        Q.add(p);
            fill(x-1,y);
            fill(x+1,y);
            fill(x,y-1);
            fill(x,y+1);
        }
        return Q;
    }
    int c(Set<Point>s){return (int)s.stream().filter(p->isBoundary(p.x,p.y)).count();}
    boolean isBoundary(int x, int y){
        return i.getRGB(x-2,y-1)!=-1||i.getRGB(x-2,y+1)!=-1||i.getRGB(x+1,y-2)!=-1||
               i.getRGB(x-1,y-2)!=-1||i.getRGB(x+2,y-1)!=-1||i.getRGB(x+2,y+1)!=-1||
               i.getRGB(x+1,y+2)!=-1||i.getRGB(x-1,y+2)!=-1;
    }
    void s(Object o,int c){
        ((Set<Point>)o).stream().forEach(p->{i.setRGB(p.x,p.y,c);});
    }
}

Bu, görüntünün her pikseli üzerinde yineleme yaparak ve bir "deliğe" her ulaştığımızda sel doldurma ile çalışır. Biz her sel dolgu sonucunu eklemek Set<Point>a Set. Sonra hangi şeklin hangisi olduğunu belirleriz. Bu, şeklin sınır piksel sayısına bakarak yapılır. Sınırı siyah bir karodan uzaklaşan bir şövalye hareketi olarak tanımladım, çünkü bu rotasyonlar arasında daha sabit kalacaktı. Bunu yaptığımızda, şekillerin şu değere göre sıralanabileceği anlaşılıyor: Daire, Kare, Üçgen, Dişli. Böylece, bu şeklin tüm piksellerini doğru renge ayarlayıp ayarlarım.

Yazdığım görüntünün doğrudan dosyadan alınmadığını, çünkü eğer bunu yaparsam Java görüntüyü siyah beyaz olarak kabul eder ve renklerle doldurmak işe yaramaz. Bu yüzden TYPE_INT_RGB(ki 1) ile kendi imajımı oluşturmak zorundayım . Ayrıca ben iş yapıyorum görüntü olduğuna dikkat 302tarafından 302; bu, şövalyenin mesafe algoritmasının görüntüdeki sınırları okumaya çalışmaktan endişe duymasına gerek kalmamasıdır. Bu tutarsızlığı büyüklükleri arayarak düzeltiyorum i.getSubImage(1,1,300,300). Not: Görüntüleri yüklediğimde bunu düzeltmeyi unutmuş olabilirim, bu durumda görüntüler 2 piksel genişliğindedir, ancak bunun dışında, doğru olmalılar

İşlev, yolu iletilen dosyanın üzerine yazacaktır. Çıktılar:

görüntü tanımını buraya girin görüntü tanımını buraya girin görüntü tanımını buraya girin görüntü tanımını buraya girin


Sınıf yönteminin yanı sıra ana yöntemdeki argümanları "a" veya benzeri şekilde kısaltarak birkaç karakter kaydedebilir.
Ryan,

@Ryan Bu sayımda sayılmaz. Sorunun izin verdiği şekilde sadece ithalatı + işlevleri sayarım.
Justin

Sanırım bunu 1000 baytın altında bulabilirim. Denemek için zaman olduğunda bunun üzerinde çalışmak gerekir.
Justin

20

Python, 571 567 528 bayt

Quincunx'un çözümüne benzer şekilde, her şekli 1 ila 4 arası bir indeksle doldurma yoluyla doldurmaya başlar, daha sonra sınırlayıcı dairelerinin yarıçapı ile şekillerin kimliğini belirler. Buna göre bir renk paleti oluşturulur ve görüntü, dizine alınmış renkli bir görüntü olarak kaydedilir.

EDIT: Şekillerin görüntü sınırına dokunmama garantisi olduğu gerçeğini kaçırdı. Daha kısa, öyleyse!

from PIL.Image import*;from numpy import*
I=open(sys.argv[1]).convert("P")
D=list(I.getdata())
W=300;R=range(W*W);N=range(5)
O=[[0,i,array([0,0])]for i in N];n=0
for i in R:
 if D[i]>4:
    n+=1;S=[i]
    while S:
     j=S.pop()
     if D[j]>4:D[j]=n;O[n][0]+=1;O[n][2]+=j%W,j/W;S+=[j+1,j-1,j+W,j-W]
for o in O[1:]:o[2]/=o[0];o[0]=0
for i in R:
 if D[i]:o=O[D[i]];v=(i%W,i/W)-o[2];o[0]=max(o[0],dot(v,v))
O.sort()
C=[0]*5+[255]*3+[0,255,0,0]*2;P=C[:]
for i in N:j=3*O[i][1];P[j:j+3]=C[3*i:3*i+3]
I.putdata(D);I.putpalette(P);I.save("o.png")

Komut satırında bir giriş dosya adı alır ve çıktının üzerine yazar o.png.


2
Argh, yapmaya çalıştığımdan çok daha basit. +1
Martin Ender

7

Mathematica 225


Güncelleme :

OP bu yaklaşımın bilgisayarla görü fonksiyonlarını kullanmasına karar verdi, bu yüzden artık çalışıyor. Ancak yayınlanan bırakacağım. Belki birileri ilgi çekici bulabilir.


f@i_ := (m = MorphologicalComponents[ImageData@i];
Image@Partition[Flatten[(m)] /. 
   Append[ ReplacePart[SortBy[ComponentMeasurements[m, "Circularity"], Last], 
   {{1, 2} -> Yellow, {2, 2} -> Green, {3, 2} -> Red, {4, 2} -> Blue}], 0 -> Black], 
Dimensions[m][[2]]])

ImageData görüntüyü 0 ve 1 'lerin matrisi olarak döndürür.

Flatten bu matrisi bir listeye dönüştürür.

Morphological Components4 piksel kümesini bulur ve kümeye göre her piksele farklı bir tamsayı, 1, 2, 3, 4 atar. (Siyah) arka plan için 0 ayrılmıştır.

ComponentMeasurements Kümelerin daireselliğini test eder.

Daima en genelinden dairesel olacak: daire, kare, üçgen ve dişli.

ReplacePart her bileşen tamsayısını dairesel sıralamayı kullanarak ilgili RGB rengiyle değiştirir.

Partition...Dimensions[m][[2]] piksel renklerinin listesini alır ve girdi görüntüsüyle aynı boyutta bir matris döndürür.

Image piksel renkleri matrisini renkli bir resme dönüştürür.

girişler

{f[img1],f[img2],f[img3],f[img4]}

çıktılar


147 karakter:f@i_:=Image[#/.Append[Thread[Ordering[Last/@ComponentMeasurements[#,"Circularity"]]->{Yellow,Green,Red,Blue}],0->Black]]&@MorphologicalComponents@i
alephalpha

Küçük nokta: renkleriniz doğru rgb değerlerine sahip değil. Asıl nokta: Bunu bilgisayarla görme kütüphanelerini veya işlevlerini kullanmayacağımı sanmam.
Calvin'in Hobileri

"Dairesellık" tartışmalı bir şekilde görseldir; Başka ne yapabilirim göreceğim. Bununla birlikte, renkler ölüdür: {RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[0, 0, 1], RGBColor[1, 1, 0]}1, 255'e karşılık gelir. Hiçbir kütüphane kullanılmamıştır.
DavidC

@ Calvin'in Hobileri Sorun MorphologicalComponents, kurallarınıza uygun olup olmadığına bağlı olarak ortaya çıkıyor . Bir kişi, her bir pikselin hangi kümeye ait olduğunu bildiğinde, hangi rakamın hangisi olduğunu belirlemek için ham piksel sayısı da dahil olmak üzere birçok yol vardır.
DavidC

Oldukça tartışmalı bir bilgisayar vizyonu işlevi olduğu ve Mathematica'ya haksız bir avantaj sağladığı için kuralları ihlal ettiğini söyleyeceğim. Renklerin doğru olması gerektiğine katılıyorum ancak görüntünüze açıkça bakıyorlar ( (255,0,22)Paint'te kontrol ettiğimde kırmızıdır ). Mathematica'm yok, bu yüzden emin olmak için koşamam.
Calvin'in Hobileri

7

Mathematica, 354 345 314 291 288

Hala golf oynamak, bir kaç karakterle kısaltılabilir, ancak performans dayanılmaz hale gelir. Şekilleri tanımlamak için Varyansı kullanır:

f=(w=Position[z=ImageData@Import@#,1];r=Nearest;v@x_:=Variance@N[Norm[Mean@x-#]&/@x];Image[Plus@@(ReplacePart[0z/. 0->{0,0,0},#->r[{108,124,196,115}->List@@@{Blue,Red,Green,Yellow},v@#][[1]]]&/@Rest@NestList[(m=r[w=w~Complement~#];FixedPoint[Union@@(m[#,{8,2}]&/@#)&,{#&@@w}])&,{},4])])&

Boşluklu:

f = (w = Position[z = ImageData@Import@#, 1];
     r = Nearest; 
     v@x_ := Variance@N[Norm[Mean@x - #] & /@ x];
     Image[Plus @@ (ReplacePart[ 0 z /. 0 -> {0, 0, 0}, # -> r[{108, 124, 196, 115} -> 
                                              List @@@ {Blue, Red, Green, Yellow}, v@#][[1]]] & /@
     Rest@NestList[(m = r[w = w~ Complement~#];
                   FixedPoint[Union @@ (m[#, {8, 2}] & /@ #) &, {# & @@ w}]) &
                   , {}, 4])]) &

Test yapmak:

s = {"http://i.stack.imgur.com/Oa2O1.png", "http://i.stack.imgur.com/C6IKR.png", 
     "http://i.stack.imgur.com/YZfc6.png", "http://i.stack.imgur.com/F1ZDM.png", 
     "http://i.stack.imgur.com/chJFi.png", "http://i.stack.imgur.com/DLM3y.png"};
Partition[f /@ s, 3] // Grid

Mathematica grafikleri

İşte tamamen ungolfed. Daha sonra açıklamalar ekleyecektir:

findOneZone[{universe_List, lastZone_List}] :=
 Module[{newUniverse, proximityFindFunc, seedElement},
  newUniverse = Complement[universe, lastZone];
  proximityFindFunc = Nearest@newUniverse;
  seedElement = {First@newUniverse};
  {newUniverse, FixedPoint[Union @@ (proximityFindFunc[#, {8, 2}] & /@ #) &, seedElement]}]

colorAssign[zone_List] :=
 Module[{
   vlist = {108, 124, 196, 115},
   cols = List @@@ {Blue, Red, Green, Yellow},
   centerVariance},
  centerVariance[x_List] := Variance@N[Norm[Mean@x - #] & /@ x];
  First@Nearest[vlist -> cols, centerVariance@zone]]

colorRules[zones_List] := (# -> colorAssign[#] & /@ zones)

main[urlName_String] := 
 Module[{pixels, FgPixelPositions, rawZones, zones},
  pixels = ImageData@Import@urlName;
  FgPixelPositions = Position[pixels, 1];
  (*fill and separate the regions*)
  rawZones = NestList[findOneZone[#] &, {FgPixelPositions, {}}, 4];
  zones = Rest[rawZones][[All, 2]];
  (*Identify,colorize and render*)
  Image@ReplacePart[ConstantArray[{0, 0, 0}, Dimensions@pixels], 
    colorRules[zones]]]

s = {"http://i.stack.imgur.com/Oa2O1.png"};
main /@ s

2

Python, 579 577 554 514 502 501 bayt

Her bir şekil için, sel doldurur, sonra centroid ve en uzak nokta arasındaki mesafeyi hesaplar.

daha sonra şeklin gerçek yüzeyi, aynı boyuta sahip bir üçgen, kare, disk veya tekerleğin yüzeyi ile karşılaştırılır.

ithalat matematiği ; dan PIL . Görüntü aktarma *; A , R , _ , I = abs , aralık ( 300 ), 255 , açık ( sys . Argv [ 1 ]). dönüştürmek ( 'P' ); S = I . Yük () için j içinde R : için I içinde R : eğer Q [ 

 
  i , j ] == _ : 
   X , Y , s , z , p = 0 , 0 , 0 , [], [( i , j )] , p : 
    a , b = n = p . Pop () ise değildir ( S [ n !] = _ veya N olarak z ): 
     X * = bir ; Y + =
   
     b ; z + = [ n ]; p + = [( a , b - 1 ), ( a + 1 , b ), ( a , b + 1 ), ( a - 1 , b )]; s + = 1 
   r = maks ([ matematik . hypot ( x / s - X , Y / s - y ) için x , y içinde z )]; C = { 1 : A ( s - ( 1.4 * r ) ** 2 ), 2 : A ( s - r * r / 3 ), 3 : A ( s - matematik . Pi * r * r ), 4 : A ( s - 2.5 * r * r )} z in p için
   : 
    S [ p ] = dakika ( , anahtar = . Olsun ) 
I . putpalette ([ 0 , 0 , 0 , _ ] * 3 + [ _ , _ , 0 ]) 
I . göster ()

1

C # 1086 bayt

Yine başka bir taşkın çözümü, burada sadece C # sürümü olmadığı için kayıt için. Quincunx gibi, kendimi bunu yapabileceğimi ve Java'daki yaklaşımına pek uyuşmadığını kanıtlamak istedim.

  • StackOverflows ile çalışmaya devam ettiğim için bu çözüm herhangi bir özyineleme (ancak bir yığın) kullanmıyor.
  • Kenarlık piksellerinin algılanması, sonraki 4 piksele bakarak basitleştirilir, bunlardan herhangi biri siyah ise, akım bir kenarlık pikselidir.

Her imageformat'ı kabul eder.

  • Parametre 1 = InputPath
  • Parametre 2 = OutputPath

Muhtemelen tüm statik maddeleri kaldırarak ve bir Program örneği oluşturarak birkaç karakterden sıyrılabilir.

Okunabilir sürüm:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;

class Program
{
    static Bitmap img;
    static int w, h;
    static ISet<Point> pointsDone = new HashSet<Point>();
    static void Main(string[] a)
    {
        img = new Bitmap(a[0]);
        w = img.Width;
        h = img.Height;
        Bitmap clone = new Bitmap(w,h, PixelFormat.Format32bppArgb);
        Graphics.FromImage(clone).DrawImage(img, 0, 0, w, h);
        img = clone;




        Color[] colors = new[] { Color.Blue, Color.Red, Color.Green, Color.Yellow };

        var shapes = new List<ISet<Tuple<bool, Point>>>();
        for(int x=0;x<w;x++)
            for (int y = 0; y < h; y++)
            {
                Point p = new Point(x, y);
                if (pointsDone.Add(p) && _isWhitePixel(p))
                    shapes.Add(_detectShape(p));
            }
        int index = 0;
        foreach (var shp in shapes.OrderBy(shp => shp.Count(item => item.Item1)))
        {
            foreach (var pixel in shp)
                img.SetPixel(pixel.Item2.X, pixel.Item2.Y, colors[index]);
            index++;
        }

        img.Save(a[1]);
    }

    private static ISet<Tuple<bool, Point>> _detectShape(Point p)
    {
        var todo = new Stack<Point>(new[] { p });
        var shape = new HashSet<Tuple<bool, Point>>();
        do
        {
            p = todo.Pop();
            var isBorderPixel = false;
            foreach (var n in new[] { new Point(p.X + 1, p.Y), new Point(p.X - 1, p.Y), new Point(p.X, p.Y + 1), new Point(p.X, p.Y - 1) })
                if (_isWhitePixel(n))
                {
                    if (pointsDone.Add(n))
                        todo.Push(n);
                }
                else isBorderPixel = true; // We know we are at the border of the shape
            shape.Add(Tuple.Create(isBorderPixel, p));

        } while (todo.Count > 0);
        return shape;
    }

    static bool _isWhitePixel(Point p)
    {
        return img.GetPixel(p.X, p.Y).ToArgb() == Color.White.ToArgb();
    }
}

golfed:

using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Imaging;using System.Linq;class P{static Bitmap a;static int w,h;static ISet<Point> d=new HashSet<Point>();static void Main(string[] q){a=new Bitmap(q[0]);w=a.Width;h=a.Height;var c=new Bitmap(w,h,PixelFormat.Format32bppArgb);Graphics.FromImage(c).DrawImage(a,0,0,w,h);a=c;var e=new[]{Color.Blue,Color.Red,Color.Green,Color.Yellow};var f=new List<ISet<dynamic>>();for(int x=0;x<w;x++)for(int y=0;y<h;y++){Point p=new Point(x,y);if (d.Add(p)&&v(p))f.Add(u(p));}int i=0;foreach(var s in f.OrderBy(s=>s.Count(item=>item.b))){foreach(var x in s)a.SetPixel(x.p.X,x.p.Y,e[i]);i++;}a.Save(q[1]);}private static ISet<dynamic> u(Point p){var t=new Stack<Point>(new[]{p});var s=new HashSet<dynamic>();do{p=t.Pop();var b=false;foreach(var n in new[]{new Point(p.X+1,p.Y),new Point(p.X-1,p.Y),new Point(p.X,p.Y+1),new Point(p.X,p.Y-1)})if(v(n)){if (d.Add(n))t.Push(n);}else b=true;s.Add(new{b,p});}while (t.Count>0);return s;}static bool v(Point p){return a.GetPixel(p.X,p.Y).ToArgb()==Color.White.ToArgb();}}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.