สแควร์, วงกลม, สามเหลี่ยม, …เกียร์?


69

การใช้Algodooและโปรแกรมระบายสีฉันสร้างภาพโมโนโครมขนาด300x300หกรูปที่มีสี่รูปร่างที่สะดวก:

ภาพ 1 ภาพที่ 2 ภาพ 3 รูปภาพ 4 ภาพ 5 ภาพที่ 6

รูปภาพของคลาสนี้มีคุณสมบัติดังต่อไปนี้:

  • พวกเขามักจะ 300 × 300 พิกเซล, monochromatic (สีดำและสีขาวเท่านั้น) และมีพื้นที่สีขาวสี่ที่ตรงกับสี่เหลี่ยม, วงกลม, สามเหลี่ยมและเกียร์
  • รูปร่างไม่ซ้อนหรือสัมผัสซึ่งกันและกันและไม่แตะขอบภาพหรือออกนอกขอบเขต
  • รูปร่างมีขนาดเท่ากันเสมอ แต่อาจหมุนและวางในลักษณะใดก็ได้

(รูปร่างยังมีพื้นที่เท่ากันแม้ว่าเมื่อ rastered เช่นนี้จำนวนพิกเซลของพวกเขาจะไม่เท่ากันอย่างแน่นอน)

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดที่เป็นไปได้ซึ่งจะอยู่ในชื่อไฟล์ของภาพและเปลี่ยนพิกเซลสีขาวทั้งหมด ...

  • สีแดง(255, 0, 0)ถ้าพวกเขาอยู่ในตาราง
  • สีน้ำเงิน(0, 0, 255)ถ้าพวกเขาอยู่ในวงกลม
  • สีเขียว(0, 255, 0)ถ้าพวกเขาอยู่ในรูปสามเหลี่ยม
  • สีเหลือง(255, 255, 0)ถ้าพวกเขาอยู่ในเกียร์

เช่น

รูปภาพ 1 สีใน

รายละเอียด

โปรแกรมของคุณควรทำงานเพื่อให้ได้ภาพอินพุตที่เป็นไปได้ทั้งหมดอย่างมีประสิทธิภาพ (จะป้อนเฉพาะภาพขาวดำขนาด 300 × 300 เท่านั้น) ภาพหกภาพที่ฉันให้ไว้เป็นเพียงตัวอย่างเท่านั้น

คุณไม่สามารถใช้ห้องสมุดหรือฟังก์ชั่นการมองเห็นของคอมพิวเตอร์ในตัวหรือภายนอก ประเด็นคือการทำเช่นนี้โดยใช้การทำงานระดับพิกเซลของคุณเอง คุณอาจใช้ไลบรารีรูปภาพที่ให้คุณเปิดและแก้ไขรูปภาพ (เช่น PIL สำหรับ Python)

คุณสามารถใช้รูปแบบไฟล์ภาพ lossless ทั่วไปสำหรับอินพุตและเอาต์พุตตราบใดที่คุณยึดตามแบบแผนชุดสี

คุณสามารถใช้ชื่อไฟล์ภาพเป็นอาร์กิวเมนต์ฟังก์ชันจาก stdin หรือจากบรรทัดคำสั่ง ภาพออกสามารถบันทึกเป็นไฟล์ใหม่ไฟล์เดียวกันหรือแสดงเพียง

เกณฑ์การให้คะแนน

การส่งที่มีไบต์น้อยที่สุดจะเป็นผู้ชนะ ฉันอาจทดสอบการส่งภาพที่มีรูปภาพเพิ่มเติมเพื่อตรวจสอบความถูกต้องของภาพ


เราอาจสมมติว่าอินพุตเป็นขาวดำโดยไม่มี anti-aliasing หรือไม่? ถ้าไม่เราอาจลบ anti-aliasing จากอินพุต anti-aliased หรือไม่
John Dvorak

@JanDvorak ใช่ โดย monochromatic ฉันหมายถึงขาวดำเท่านั้นจึงไม่สามารถลบรอยหยักได้
งานอดิเรกของ Calvin

1
เราต้องการรูปแบบการป้อนข้อมูลที่เฉพาะเจาะจงอย่างแม่นยำมากกว่าเพียงแค่นามสกุลไฟล์หรือไม่ คือฉันต้องการอินพุตASCII PBMโดยไม่มีความเห็นใด ๆ อยู่ภายใน
John Dvorak

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

นี่เป็นเกมที่สนุกมาก!

ฉันนำชิ้นส่วนที่เชื่อมต่อกลับมาใช้ใหม่สำหรับความท้าทาย "ฉันอยู่ในห้องที่ใหญ่ที่สุด"และใช้อัตราส่วนระหว่างค่าเฉลี่ยและระยะทางสูงสุดของทุกจุดต่อศูนย์กลางของแต่ละองค์ประกอบ ฉันตัดสินสำหรับเรื่องนี้เนื่องจากทั้งขนาดและการหมุนคงที่และเห็นได้ชัดว่าดีพอที่จะแยกแยะความแตกต่างระหว่างรูปร่างตามที่กำหนด การจัดอันดับค่านี้จากต่ำไปสูงให้วงกลมคำสั่งเกียร์สแควร์และสามเหลี่ยมที่ใช้ในการเปลี่ยนรูปแบบของตารางสี

แสดงผลลัพธ์โดยใช้ viewmap addon ไม่มีการใช้กล่องเครื่องมือยกเว้นการอ่านไฟล์และเอาต์พุต

ความทนทานไม่ได้เป็นข้อกำหนด แต่จะใช้เวลา 18 ไบต์ 2 ช่องว่างที่ไม่จำเป็นเพิ่มขึ้นแทนที่&.>ด้วย&>ในratioและ&.:โดย&:dcent อีก 2 ไบต์

ได้รับอย่างมากทั้งในช่วงเวลาสั้น ๆ และประสิทธิภาพในการcompใช้งานการเปลี่ยนแทนที่จะเป็นcut( ;.) วิธีนี้ภาพจะถูกจำลองและเลื่อนใน 8 ทิศทางแทนที่จะสแกนด้วยหน้าต่าง 3x3

idฟังก์ชั่นที่ซับซ้อนขันสำหรับสิ่งที่จะต้องทำ ตอนนี้มันจะกำหนด id ของพิกเซลในวัตถุโดยการคูณภาพด้วยอาร์เรย์ของตัวเลขที่ไม่ซ้ำกันดังนั้นการตั้งค่า BG เป็นศูนย์

รหัสอธิบายเพิ่มเติมอีกเล็กน้อย:

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 "รูปทรงไม่เคยซ้อนทับหรือสัมผัสกันและพวกเขาไม่ได้สัมผัสกับเส้นขอบภาพหรือออกไปนอกขอบเขต"
ดร. เบลิซาเรี

ขอบคุณนั่นเป็นประโยชน์ (อันที่จริงฉันหมายถึงพิกเซลด้านบนซ้ายเป็นครั้งแรกใน ravel) วิธีนี้จะกำจัดการตรวจจับพื้นหลัง (22 ไบต์)
jpjacobs

ลดความยาวลงอย่างมากและเพิ่มประสิทธิภาพ :)
jpjacobs

29

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

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

ฉันสามารถประหยัดได้อีก 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

Java, 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; เช่น boilerplate เพิ่ม):

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จากนั้นเราจะพิจารณาว่ารูปร่างใดเป็นรูปร่างใด สิ่งนี้ทำได้โดยดูที่จำนวนพิกเซลขอบเขตของรูปร่าง ฉันกำหนดขอบเขตเป็นอัศวินย้ายออกจากกระเบื้องสีดำเนื่องจากจะคงที่มากขึ้นระหว่างการหมุนและเช่น เมื่อเราทำสิ่งนี้จะเห็นได้ชัดว่ารูปร่างสามารถเรียงตามค่าดังกล่าว: วงกลม, สแควร์, สามเหลี่ยม, เกียร์ ดังนั้นฉันจึงจัดเรียงและตั้งค่าพิกเซลทั้งหมดของรูปร่างนั้นเป็นสีที่ถูกต้อง

โปรดทราบว่าภาพที่ฉันเขียนถึงไม่ได้ถูกนำมาจากไฟล์โดยตรงเพราะถ้าฉันทำเช่นนั้น Java จะถือว่าภาพเป็นขาวดำและการเติมด้วยสีจะไม่ทำงาน ดังนั้นฉันต้องสร้างภาพของตัวเองด้วยTYPE_INT_RGB(ซึ่งก็คือ1) นอกจากนี้ยังทราบว่าภาพที่ผมทำผลงานในการเป็น302โดย302; นี่คือเพื่อให้อัลกอริทึมระยะทางของอัศวินไม่จำเป็นต้องกังวลเกี่ยวกับความพยายามที่จะอ่านนอกขอบเขตของภาพ i.getSubImage(1,1,300,300)ฉันจะแก้ไขปัญหาความแตกต่างนี้ในขนาดโดยการเรียก หมายเหตุ: ฉันอาจลืมแก้ไขเมื่อฉันอัปโหลดภาพซึ่งในกรณีนี้ภาพมีความกว้าง 2 พิกเซล แต่ยกเว้นความจริงข้อนี้ควรจะถูกต้อง

ฟังก์ชั่นจะเขียนทับไฟล์ที่มีการส่งผ่านพา ธ

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


สามารถบันทึกอักขระสองสามตัวโดยย่อชื่อคลาสรวมทั้ง args ในเมธอด main เป็น "a" หรือคล้ายกัน
Ryan

@ Ryan ผู้ที่ไม่ได้นับ ฉันนับเฉพาะการนำเข้า + ฟังก์ชั่นตามที่อนุญาตโดยคำถาม
Justin

ฉันคิดว่าฉันอาจได้รับนี้น้อยกว่า 1,000 ไบต์ ต้องทำงานในภายหลังเมื่อมีเวลาลอง
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

Mathematica 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 Componentsค้นหาพิกเซล 4 กลุ่มและกำหนดจำนวนเต็ม 1, 2, 3, 4 ให้กับแต่ละพิกเซลตามกลุ่ม 0 สงวนไว้สำหรับพื้นหลัง (สีดำ)

ComponentMeasurements ทดสอบความเป็นวงกลมของกลุ่ม

ตั้งแต่วงกลมไปจนถึงน้อยที่สุด: วงกลมสี่เหลี่ยมสามเหลี่ยมและเกียร์

ReplacePart แทนที่แต่ละจำนวนเต็มองค์ประกอบด้วยสี RGB ที่เกี่ยวข้องโดยใช้การเรียงลำดับเวียน

Partition...Dimensions[m][[2]] รับรายการพิกเซลสีและส่งกลับเมทริกซ์ในมิติเดียวกับภาพที่นำเข้า

Image แปลงเมทริกซ์ของสีพิกเซลเป็นภาพสี

ปัจจัยการผลิต

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

เอาท์พุท


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

จุดเล็กน้อย: สีของคุณไม่มีค่า rgb ที่ถูกต้อง จุดสำคัญ: ฉันไม่แน่ใจว่าฉันจะนับว่าไม่ได้ใช้ห้องสมุดหรือฟังก์ชั่นการมองเห็นของคอมพิวเตอร์
งานอดิเรกของ Calvin

"หนังสือเวียน" เป็นเนื้อหาที่มองเห็นได้ ฉันจะเห็นสิ่งอื่นที่ฉันสามารถทำได้ อย่างไรก็ตามสีจะตายเมื่อ: {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)เมื่อฉันตรวจสอบใน Paint) ฉันไม่มี Mathematica ดังนั้นฉันไม่สามารถเรียกใช้เพื่อให้แน่ใจ
งานอดิเรกของ Calvin

7

Mathematica, 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

กราฟิกทางคณิตศาสตร์

ที่นี่มันไม่สมบูรณ์ จะเพิ่มคำอธิบายในภายหลัง:

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 ไบต์

สำหรับแต่ละรูปร่างน้ำท่วมเติมมันแล้วคำนวณระยะห่างระหว่างเซนทรอยด์และจุดที่ไกลที่สุด

จากนั้นพื้นผิวจริงของรูปร่างจะถูกเปรียบเทียบกับพื้นผิวของรูปสามเหลี่ยมสี่เหลี่ยมแผ่นดิสก์หรือล้อที่มีขนาดเท่ากัน

นำเข้าทางคณิตศาสตร์; จากPIL นำเข้ารูปภาพ*; A , R , _ , I = abs , ช่วง( 300 ), 255 , เปิด( sys . argv [ 1 ]) แปลง( 'P' ); Q = ฉัน load () สำหรับj ในR : สำหรับi ในR : if Q [ 

 
  ฉัน, J ] == _ : 
   X , Y , s , Z , P = 0 , 0 , 0 , [], [( ฉัน, 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 : A ( s - ( 1.4 * r ) ** 2 ), 2 : A ( s - r * r / 3 ), 3 : A ( s - คณิตศาสตร์. pi * r * r ), 4 : A ( s - 2.5 * r * r )} สำหรับp ในz
   : 
    Q [ P ] = นาที( C , คีย์= C . ได้รับ) ผม
putpalette ([ 0 , 0 , 0 , _ ] * 3 + [ _ , _ , 0 ]) ฉัน
แสดง()

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.