정사각형, 원형, 삼각형,… 기어?


69

Algodoo 와 Paint를 사용하여 다음 4 가지 편리한 모양의 300x300 단색 이미지 6 개를 만들었습니다.

이미지 1 이미지 2 이미지 3 이미지 4 이미지 5 이미지 6

이 이미지 클래스에는 다음과 같은 속성이 있습니다.

  • 항상 300 × 300 픽셀이며 단색 (흑백 만 해당)이며 정사각형, 원, 삼각형 및 기어에 해당하는 정확히 4 개의 흰색 영역이 있습니다.
  • 도형이 서로 겹치거나 닿거나 이미지 테두리에 닿거나 경계를 벗어나지 않습니다.
  • 모양은 항상 같은 크기이지만 어떤 식 으로든 회전하고 배치 할 수 있습니다.

(이와 같이 래스터 화 될 때 픽셀 수는 정확히 동일하지는 않지만 모양의 면적도 동일합니다.)

도전

그러한 이미지의 파일 이름을 사용하고 모든 흰색 픽셀을 돌리는 가능한 가장 짧은 프로그램이나 기능을 작성하십시오 ...

  • (255, 0, 0)그들이 광장에 있다면 빨간색 .
  • (0, 0, 255)원 안에 있으면 파란색이 됩니다.
  • (0, 255, 0)삼각형 안에 있으면 녹색 입니다.
  • (255, 255, 0)기어 안에 있으면 노란색 입니다.

예 :

컬러 1 이미지

세부

프로그램은 가능한 모든 입력 이미지를 효과적으로 작동시켜야합니다. (유효한 300x300 단색 이미지 만 입력됩니다.) 제가 제공 한 6 개의 이미지는 단지 예일 뿐이며, 출력을 프로그램에 하드 코딩하지 않을 수도 있습니다.

내장 또는 외장 컴퓨터 비전 라이브러리 또는 기능을 사용할 수 없습니다. 요점은 자신의 픽셀 수준 작업을 사용 하여이 작업을 수행하는 것입니다. 단순히 이미지를 열고 수정할 수있는 이미지 라이브러리를 사용할 수 있습니다 (예 : PIL for Python).

색 구성표를 고수하는 한 일반적인 손실없는 이미지 파일 형식을 입력 및 출력에 사용할 수 있습니다.

이미지 파일 이름을 stdin 또는 명령 행에서 함수 인수로 사용할 수 있습니다. 출력 이미지는 새 파일, 동일한 파일로 저장하거나 간단히 표시 할 수 있습니다.

채점

가장 적은 바이트를 가진 제출이 이깁니다. 추가 이미지로 제출 한 내용을 테스트하여 그 유효성을 확인할 수 있습니다.


앤티 앨리어싱이없는 입력이 흑백이라고 가정 할 수 있습니까? 그렇지 않은 경우 앤티 앨리어싱 입력에서 앤티 앨리어싱을 제거 할 수 있습니까?
— John Dvorak '11

@JanDvorak 예. 단색은 흑백 만 의미하므로 앤티 앨리어싱이 불가능합니다.
— Calvin 's Hobbies

1
파일 확장명보다 더 정확하게 특정 입력 형식이 필요할 수 있습니까? 즉, 내부에 주석이없는 ASCII PBM 입력을 원합니다 .
— John Dvorak '11

12
그래서 ...이 문제를 해결하려고했지만 이 이미지로 끝났습니다 . 어떻게해야할지 모르겠지만 멋진 모습입니다. : P
— Doorknob

2
Ell과 같은 아이디어이지만 더 나쁜 솔루션이므로 솔루션을 게시하고 싶지 않습니다. 하지만 난 그냥이 :) 할 수있는 즐거운 작은 도전이었다 싶은 말
— 크리스 버트 - 브라운

답변:


8

J- 246,224 185 바이트

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

이것은 재미있었습니다!

나는 "가장 큰 방에 있습니다"도전에 사용한 연결된 구성 요소 부분을 재사용하고 각 구성 요소의 중심에 대한 모든 지점의 평균 거리와 최대 거리 사이의 비율을 사용했습니다. 나는 스케일과 회전이 변하지 않기 때문에 이것을 해결했으며, 주어진 모양을 구별하기에 충분합니다. 이 값을 낮음에서 높음으로 순위를 매기면 컬러 맵을 순열시키는 데 사용되는 주문 원, 기어, 사각형 및 삼각형이 나타납니다.

뷰맵 애드온을 사용하여 결과를 표시합니다. 파일 읽기 및 출력을 제외하고 도구 상자가 사용되지 않았습니다.

견고성은 요구 사항이 아닌 것 같습니다. 18 바이트를 차지합니다. 대체 2 개 이상의 불필요한 공간 &.>으로 &>의 ratio및 &.:에 의해 &:다른 2 바이트 dcent있다.

( ) comp대신 시프 팅 을 사용 하면 부족함과 성능이 크게 향상 됩니다 . 이 방법으로 이미지를 3x3 창으로 스캔하는 대신 8 방향으로 복제 및 이동합니다.cut;.

이 id기능은해야 할 일에 엄청나게 복잡했습니다. 이제 이미지에 고유 한 숫자의 배열을 곱하여 BG를 0으로 설정하여 객체의 픽셀에 id를 할당합니다.

좀 더 설명해주세요 :

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

이것에 대해 자세히 설명하기는 조금 길지만 관심이 있다면 할 것입니다.


오른쪽 상단 픽셀은 bg입니다. OP에 따르면 "모양은 서로 겹치거나 닿지 않으며 이미지 테두리를 만지거나 범위를 벗어나지 않습니다."
— Dr. belisarius

감사합니다. (실제로 나는 왼쪽 상단 픽셀을 의미했습니다. 이는 백그라운드 감지를 줄입니다 (22 바이트).
— jpjacobs

극적으로 :) 길이 감소 및 성능을 증가
— jpjacobs

29

매스 매 티카, 459 392 바이트

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]]])&

언 골프 드 :

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]]]
) &

나는 돌려 6 바이트 이상을 절약 할 수 m=1.Mean@a;m=#-m&/@a;로 m=#-Mean@a&/@a;,하지만 크게 테스트 짜증나는 실행 시간을, 불면. (이 두 최적화 즉, 주 :의 계산 꺼내 Mean@a루프 아웃 및 . 부동 소수점 숫자 대신 정확한 기호 유형을 사용 흥미롭게도, 정확한 타입의 사용은 훨씬 더 중요한 반복마다의 평균을 계산하기보다는).

이것이 세 번째 접근 방식입니다.

  • 홍수로 지역을 탐지하십시오.
  • 모든 픽셀 좌표를 평균하여 각 영역의 대략적인 중심을 찾으십시오.
  • 이제 모양의 모든 픽셀에 대해 거리 대 각도에서 그 중심까지의 거리를 그려 봅시다.

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

    삼각형은 일정한 반경에 대한 앨리어싱 변동으로 인해 3의 명확한 최대 값, 사각형 4, 기어 16 및 원의 톤을가집니다.

  • 300 픽셀의 조각 (각도 순서)을보고 최대 값을 찾고 위치의 픽셀 150이 최대 인 조각을 계산합니다 .
  • 그런 다음 피크 수에 따라 모든 픽셀에 색상을 지정합니다 (원은 16 이상이며 일반적으로 슬라이스 크기로 인해 약 20 개의 피크를 생성합니다).

기록을 위해 Ell의 아이디어를 사용하고 단순히 픽셀과 중심 사이의 가장 큰 거리로 영역을 정렬하면 342 바이 트로이 작업을 수행 할 수 있습니다.

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]]])&

그러나 나는 다른 사람들이 다른 알고리즘을 사용하지 않고 자신의 고유 알고리즘을 사용하는 한 경쟁하지 않을 것입니다.


가장 흥미로운 해결책!
— CSharpie

25

자바, 1204 1132 1087 1076

내가 이것을 할 수 있다는 것을 나 자신에게 증명하기 위해서 .

함수 선언 바로 옆에 가져 오기를 포함 시켰습니다. 이것이 작동하려면 클래스 외부에 있어야합니다.

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 (및 runnable; 즉, 상용구 추가) :

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);});
    }
}

이것은 이미지의 모든 픽셀을 반복하고 "구멍"에 도달 할 때마다 플러드 필링으로 작동합니다. 각 플러드 필 결과를에 Set<Point>에 추가합니다 Set. 그런 다음 어떤 모양이 어떤 것인지 결정합니다. 모양의 경계 픽셀 수를 보면됩니다. 나는 회전과 그 사이에서 더 일정하게 유지되기 때문에 기사가 검은 타일에서 멀어 지도록 경계를 정의했습니다. 이렇게하면 Circle, Square, Triangle, Gear 등의 값으로 모양을 정렬 할 수 있습니다. 그래서 해당 모양의 모든 픽셀을 올바른 색상으로 정렬하고 설정합니다.

내가 쓰고있는 이미지는 파일에서 직접 가져 오지 않습니다.이를 수행하면 Java가 이미지를 흑백으로 처리하고 색상을 채우는 것이 작동하지 않기 때문입니다. 그래서 난 내 자신의 이미지를 만들 필요 TYPE_INT_RGB(하다 1). 또한 내가 작업을하고있어 이미지가 있습니다 302에 의해 302; 이것은 기사의 거리 알고리즘이 이미지에서 범위를 벗어난 값을 읽는 것에 대해 걱정할 필요가 없도록하기위한 것입니다. 전화로이 불일치를 수정합니다 i.getSubImage(1,1,300,300). 참고 : 이미지를 업로드 할 때이 문제를 해결하지 못한 경우가 있습니다.이 경우 이미지의 너비가 2 픽셀이지만이 사실을 제외하고는 정확해야합니다

함수는 경로가 전달 된 파일을 덮어 씁니다. 출력 :

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


기본 메소드의 args뿐만 아니라 클래스 이름을 "a"또는 이와 유사한 것으로 줄여서 몇 개의 문자를 저장할 수 있습니다.
— Ryan

@Ryan 카운트에 포함되지 않습니다. 질문에 허용 된대로 수입 + 함수 만 계산합니다.
— 저스틴

1000 바이트 미만에서이를 얻을 수 있다고 생각합니다. 나중에 시도 할 시간이있을 때이 작업을 수행해야합니다.
— Justin

20

파이썬, 571 567 528 바이트

Quincunx의 솔루션과 유사하게 각 모양을 1에서 4까지의 지수로 플러딩하여 시작합니다. 그런 다음 경계 원의 반지름으로 모양의 정체성을 결정합니다. 이에 따라 색상 표가 구성되고 이미지가 색인 색상 이미지로 저장됩니다.

편집 : 도형이 이미지 테두리에 닿지 않도록 보장된다는 사실을 놓쳤습니다. 그렇다면 짧습니다!

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

명령 행에서 입력 파일 이름을 사용하여에 출력을 씁니다 o.png.


2
아아, 그건 내가하려고하는 것보다 훨씬 간단합니다. +1
— Martin Ender

7

매스 매 티카 225


업데이트 :

OP는이 접근법이 컴퓨터 비전 기능을 사용하기로 결정했기 때문에 더 이상 운영되지 않습니다. 그러나 게시 한 상태로 두겠습니다. 아마도 누군가가 관심을 가질 수도 있습니다.


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 이미지를 0과 1의 행렬로 반환합니다.

Flatten 해당 행렬을 목록으로 변환합니다.

Morphological Components4 개의 픽셀 클러스터를 찾고 클러스터에 따라 각 픽셀에 고유 한 정수 1, 2, 3, 4를 할당합니다. 0은 (검은 색) 배경으로 예약되어 있습니다.

ComponentMeasurements 클러스터의 원형도를 테스트합니다.

원형, 정사각형, 삼각형 및 기어는 항상 원형부터 원형까지입니다.

ReplacePart 순환 정렬을 사용하여 각 구성 요소 정수를 해당 RGB 색으로 바꿉니다.

Partition...Dimensions[m][[2]] 픽셀 색상 목록을 가져와 입력 이미지와 동일한 차원의 행렬을 반환합니다.

Image 픽셀 색상의 행렬을 컬러 이미지로 변환합니다.

입력

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

출력


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

사소한 점 : 색상에 올바른 rgb 값이 없습니다. 주요 요점 : 컴퓨터 비전 라이브러리 나 기능을 사용하지 않는 것으로 생각합니다.
— Calvin 's Hobbies

"순환 성"은 분명히 시각적입니다. 내가 할 수있는 다른 일을 볼 수 있습니다. 그러나 색상은 다음에서 죽은 상태입니다. {RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[0, 0, 1], RGBColor[1, 1, 0]}여기서 1은 255에 해당합니다. 라이브러리는 사용되지 않았습니다.
— DavidC

@ Calvin'sHobbies이 문제는 MorphologicalComponents규칙을 충족시키는 지 아니면 위반 하는지에 따라 결정됩니다. 각 픽셀이 어느 클러스터에 속하는지 알게되면, 원시 픽셀 수를 포함하여 어떤 그림이 어떤 것인지 결정하는 여러 가지 방법이 있습니다.
— DavidC

나는 그것이 컴퓨터 비전 기능이라고 할 수 있기 때문에 규칙을 위반한다고 말하고 Mathematica에게 불공평 한 이점을 제공합니다. 색상이 정확해야 하지만 이미지에서 잘 보이지 않습니다 ( (255,0,22)페인트를 칠할 때 빨간색 ). Mathematica가 없어서 도망 칠 수 없습니다.
— Calvin 's Hobbies

7

매쓰, 354 345 314 291 288

아직도 골프는 몇 문자 더 짧아 질 수 있지만 성능은 견딜 수 없게됩니다. 변형을 사용하여 모양을 식별합니다.

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])])&

간격으로 :

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])]) &

테스트 :

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 그래픽

여기는 완전히 풀려 있습니다. 나중에 설명을 추가합니다 :

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

파이썬, 579 577 554 514 502 501 바이트

각 모양에 대해 플러드 칠한 다음 중심과 가장 먼 지점 사이의 거리를 계산합니다.

그런 다음 모양의 실제 표면은 크기가 같은 삼각형, 사각형, 디스크 또는 바퀴의 표면과 비교됩니다.

수입 수학 ; 에서 PIL . 이미지 가져 오기 *; , R , _ , I = ABS , 범위 ( 300 ), (255) , 오픈 ( SYS . 는 argv [ 1 ]). 변환 ( 'P' ); Q = I 입니다. 부하 () 에 대한 J 에 R : 위한 I 에서 R : 만약 Q [ 

 
  I , J ] == _ : 
   X , Y , S , Z , P = 0 , 0 , 0 , [] [( I , J )] 동안 P : , B = N = P . 팝 () 만약 하지 ( Q [ N ! = _ 또는 N 에서 Z ) 
     X + = ; Y + =
   
     b ; z + = [ n ]; p + = [( a , b - 1 ), ( a + 1 , b ), ( a , b + 1 ), ( a - 1 , b )]; S + = 1 
   , R = 최대 ([ 수학 . hypot ( X / S - X , Y / S - Y ) 에 대한 X , Y 에서 , Z )]; C = { 1 : ( S - (+ 1.4 * R ) ** 2 ), 2 : ( S - R * R / 3 ) 3 : ( S - 수학 . 파이 * r에 *를 R ) 4 : ( (S) - 2.5 * R에 *를 R )} 에 대한 P 의 Z
   : 
    Q [ P ] = 분 ( C , 키 = C . 얻기 ) 
I를 . putpalette ([ 0 , 0 , 0 , _ * 3 + [ _ , _ , 0 ]) 
I . 표시 ()

1

C # 1086 바이트

여기에 C # 버전이 없으므로 기록을위한 또 다른 플러드 필 솔루션입니다. Quincunx 와 마찬가지로 나는 내가 할 수 있다는 것을 스스로 증명하고 싶었고 Java에서의 그의 접근 방식과 크게 다르지 않습니다.

  • 이 솔루션은 StackOverflows를 계속 실행하기 때문에 재귀 (그러나 스택)를 사용하지 않습니다.
  • 다음 4 개의 픽셀을 보면 경계 픽셀의 감지가 간단 해집니다. 그 중 하나가 검은 색이면 전류는 경계 픽셀입니다.

모든 이미지 형식을 받아들입니다.

  • 매개 변수 1 = InputPath
  • 매개 변수 2 = OutputPath

모든 정적 요소를 제거하고 프로그램 인스턴스를 작성하여 몇 가지 문자를 제거 할 수 있습니다.

읽을 수있는 버전 :

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();
    }
}

골프 :

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();}}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.