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


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.