วงกลมสีแดงด้วยมือเปล่า


19

มากกว่าในhttp://meta.stackoverflow.comเรามีมส์ของเราเอง หนึ่งในนั้นคือวงกลมสีแดงด้วยมือเปล่า

ดูโพสต์นี้ :

ดังนั้นความท้าทายคือ

คุณวาดวงกลมสีแดงด้วยมือเปล่าด้วยรหัสได้ไหม

ข้อ จำกัด เพิ่มเติม:

  • คุณจะถ่ายภาพเป็นอินพุตและคุณต้องส่งภาพออกโดยเพิ่มวงกลมสีแดงด้วยมือเปล่า
  • จะต้องคาดเดาได้เช่นภาพอินพุตเดียวกันจะต้องส่งออกผลลัพธ์เดียวกัน คุณสามารถใช้การสุ่มได้ แต่ผลลัพธ์จะต้องสอดคล้องกับอินพุตเดียวกัน
  • ผลลัพธ์จะต้องเป็นรูปแบบเดียวกับอินพุตยกเว้นวงกลม (ไม่มีการดัดแปลงอื่น ๆ )
  • วงกลมสีแดงด้วยมือเปล่าจะต้องดูด้วยมือเปล่า (ไม่มีวงกลมที่สมบูรณ์แบบ!) เป็นสีแดง (ชัด) และโดยทั่วไปจะมีลักษณะเป็นวงกลม

นี่คือการดังนั้นคำตอบของผู้ที่โหวตมากที่สุดเมื่อต้นเดือนมีนาคม 2014 จะเป็นผู้ชนะ ไม่มีเป้าหมายที่เฉพาะเจาะจงนอกจาก "วงกลมสีแดงด้วยมือเปล่า" ดังนั้นจงสร้างสรรค์ให้มากที่สุดเท่าที่จะทำได้เพื่อให้คุณได้รับการโหวตมากที่สุด! (เพื่อให้เป็นกลางที่สุดเท่าที่จะทำได้ฉันจะถอนคำตอบใด ๆ ที่เป็นไปตามกฎ)


11
ฉันคิดว่านี่ต้องชี้แจงเพิ่มเติมอีกเล็กน้อย เราจะก) วาดอะไรเลยนอกจากวงกลมบนผืนผ้าใบสีขาวธรรมดาข) ถ่ายภาพที่มีข้อความและวาดวงกลมรอบ ๆ บล็อคข้อความหรือ c) เอาข้อความและสร้างภาพของข้อความด้วย a วงกลมรอบ ๆ มัน?
primo

3
+1 ถึง @primo นอกจากนี้ยังมีสิ่งอื่น ๆ ที่ควรพิจารณา: หากเราต้องทำคือวาดวงกลมมันเป็นวงกลมเดียวกันทุกครั้งหรือโปรแกรมจำเป็นต้องสามารถวาดวงกลมต่าง ๆ ได้ - และวงกลมเหล่านั้นจะแตกต่างกันแบบสุ่ม หรือระบุอย่างใดโดยการป้อนข้อมูลของผู้ใช้? โปรแกรมจำเป็นต้องมีความสามารถในการจัดการอินพุตของผู้ใช้เลยเพื่อกำหนดขนาดหรือรูปร่างของวงกลมหรือไม่? มันมีความสำคัญต่อรูปแบบของสัญญาณภาพหรือไม่ใครบางคนอาจจะคิดด้วยศิลปะ ASCII ที่ชาญฉลาด?
Iszi

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

ฉันไม่รู้ว่าอะไรชัดเจนเกี่ยวกับคำถามนี้ @Iszi - คำสำคัญคือมือเปล่า เปิดโปรแกรม Paint หรือ GIMP แล้ววาดวงกลมด้วยมือเปล่าพวกมันทั้งหมดมีหน้าตาเหมือนกันหรือไม่? จากคำอธิบายและลิงก์ดูเหมือนว่าคุณจะต้องวาดวงกลมรอบ ๆ สิ่งซึ่งหมายความว่า X & Y และขนาด รูปแบบไฟล์ที่คุณใช้มีความสำคัญอย่างไร? เพียงแค่เรียกใช้ผ่านตัวแปลงหากคุณต้องการ PNG, JPEG หรืออะไรก็ตาม

ฉันเชื่อกับแม็คเคย์ หากคุณต้องการผู้โหวตมากขึ้นให้วาดวงกลมด้วยมือเปล่าแบบสุ่ม มิฉะนั้นให้เข้ารหัสวงกลมของคุณใน
Hosch250

คำตอบ:


13

C - ประมาณ750 720 ไบต์หากถูกบีบ*

ฉันคิดว่าฉันมากับสิ่งที่ดูฟรีด้วยมือ - พอ

  • เริ่มต้นที่มุมสุ่ม
  • วาดวงกลมเต็มบวกหรือลบสักเล็กน้อย
  • ใช้เส้นหนาไก่เขี่ย (อาจไก่เขี่ยเกินไป !)
  • สามารถปรับแต่งได้โดยการเปลี่ยนMAGICตัวเลข

รวบรวม:

gcc -o freehand freehand.c -lm

วิ่ง:

./freehand [X center in % W] [Y center in % H] [radius in % diagonal] < [PPM file input] > [PPM file output]

ตัวอย่าง:

./freehand 28.2 74.5 3.5 < screenshot.ppm > freehand.ppm

ก่อน:

ก่อน

หลังจาก:

หลังจาก

รหัส:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define MAGIC      42
#define UNIFORM(x) ((x) * (double)rand() / (double)RAND_MAX)

typedef struct {unsigned char r, g, b;} RGB;

int main(int argc, char **argv)
{
    int W, H, i, f, g, x, y;
    double X, Y, R, a, r;
    RGB *p;

    srand(MAGIC);

    if (argc != 4 || scanf("P6 %d %d 255\n", &W, &H) != 2)
        return 1;

    p = malloc(sizeof(RGB) * W * H);

    fread(p, sizeof(RGB), W * H, stdin);

    X = W * atof(argv[1]) / 100.0;
    Y = H * atof(argv[2]) / 100.0;
    R = hypot(W, H) * atof(argv[3]) / 100.0;

    for (a = UNIFORM(M_PI), i = 2.0 * M_PI * R + UNIFORM(R / 4.0), r = R; i > 0; i--, a += 1.0 / R)
    {
        r += UNIFORM(2.0) - 1.0;
        f = sin(a) * r + X;
        g = cos(a) * r + Y;

        for (x = f - 2; x <= f + 2; x++)
        {
            for (y = g - 2; y <= g + 2; y++)
            {
                if (x >= 0 && x < W && y >= 0 && y < H)
                {
                    RGB *s = p + y * W + x;
                    s->r = 255;
                    s->g = 0;
                    s->b = 0;
                }
            }
        }
    }

    printf("P6 %d %d 255\n", W, H);
    fwrite(p, sizeof(RGB), W * H, stdout);

    free(p);

    return 0;
}

* และใช้UสำหรับUNIFORMและMสำหรับMAGIC


25

ไลบรารี C + GD

แทนที่จะแค่วาดวงกลมเก่า ๆ ที่ฉันคิดว่ามันคงจะสนุกถ้าได้เจออะไรสีแดงในภาพและวาดวงกลมรอบ ๆ นั้น

นี่คือตัวอย่างบางส่วนของผลที่ได้รับเป็นกับ ไม่กี่ภาพจากวิกิมีเดียคอมมอนส์ :

สิ่งที่สีแดงกับวงกลมปรากฏขึ้นรอบตัวพวกเขา

และนี่คือรหัส มันค่อนข้างยุ่ง แต่ไม่ยากเกินกว่าจะติดตามฉันหวังว่า:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gd.h>

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))

/* Used for image segmentation */
int floodfill(int *tmp, int i, int w, int id) {
  int np=1;
  tmp[i]=id;
  if (tmp[i-w-1]<0) np+=floodfill(tmp,i-w-1,w,id);
  if (tmp[i-w]<0) np+=floodfill(tmp,i-w,w,id);
  if (tmp[i-w+1]<0) np+=floodfill(tmp,i-w+1,w,id);
  if (tmp[i-1]<0) np+=floodfill(tmp,i-1,w,id);
  if (tmp[i+1]<0) np+=floodfill(tmp,i+1,w,id);
  if (tmp[i+w-1]<0) np+=floodfill(tmp,i+w-1,w,id);
  if (tmp[i+w]<0) np+=floodfill(tmp,i+w,w,id);
  if (tmp[i+w+1]<0) np+=floodfill(tmp,i+w+1,w,id);
  return np;
}

int main(int argv, char *argc[]) {
  FILE          *infile,*outfile;
  gdImagePtr    img;
  int           *t, *tmp;
  int           w,h,x,y,r,g,b;
  int           c,redness,rgb;
  int           i,np,max,min,thresh;
  int           xt,yt,n;
  int           areaID,size,maxID;
  double        xmin,ymin,xmax,ymax,rad,r0,th;
  gdPoint       v[33];


  /* Check command line and open source JPEG file */
  if (argv!=3) return printf("Usage: %s <in.jpg> <out.jpg>\n",argc[0]);
  if (!(infile=fopen(argc[1],"r"))) return printf("Can't open <%s>\n",argc[1]);
  if (!(img=gdImageCreateFromJpeg(infile))) return printf("Bad JPEG: <%s>\n",argc[1]);
  fclose(infile);

  /* Extract red pixels and auto-threshold */
  w=img->sx;
  h=img->sy;
  np=w*h;
  t=tmp=calloc(np,sizeof(int));
  for (max=0,min=255,y=1;y<h-1;y++) {
    for (x=1;x<w-1;x++) {
      rgb=gdImageGetTrueColorPixel(img,x,y);
      r = (rgb&0xff0000)>>16;
      g = (rgb&0xff00)>>8;
      b = rgb&0xff;
      redness = max(0,r-(max(g,b)+abs(g-b)));
      if (redness>max) max=redness;
      if (redness<min) min=redness;
      *t++ = redness;
    }
    t += 2;
  }
  thresh = (max+min)/2;
  for (t=tmp,i=0;i<np;i++,t++) *t=((*t>thresh)?-1:0);

  /* Label each area detected */
  areaID=1;
  maxID=0;
  max=-1;
  for (t=tmp,i=0;i<np;i++,t++) {
    if (*t<0) {
      size=floodfill(tmp,i,w,areaID);
      if (size>max) {
        max = size;
        maxID = areaID;
      }
      areaID++;
    }
  }

  /* Calculate centre coordinates and area */
  if (max>0) {
    xt=yt=n=xmax=ymax=0;
    xmin=w; ymin=h;
    for (t=tmp,y=0;y<h;y++) {
      for (x=0;x<w;x++) {
        if (*t++==maxID) {
          xt+=x;
          yt+=y;
          n++;
          if (x<xmin) xmin=x;
          if (y<ymin) ymin=y;
          if (x>xmax) xmax=x;
          if (y>ymax) ymax=y;
        }
      }
    }
    x = xt/(2*n) + (xmax+xmin)/4;
    y = yt/(2*n) + (ymax+ymin)/4;

    r0 = max(20,min(min(w,h),max(xmax-xmin,ymax-ymin))/2);
  }
  /* Default circle if nothing found */
  else {
    x=w/2; y=h/2; r0=min(w,h)/3;
  }

  /* Draw a red circle */
  for (th=4.0,i=0;i<33;i++) {
    rad = r0 * (1.2 + (" ,<MYZVSB>@EJIOSWZfgb^bbfgeZTOI@2"[i]-87)/160.0);
    v[i].x = x + rad * sin(th);
    v[i].y = y + rad * cos(th);
    th += 0.22;
  }
  gdImageSetThickness(img,7);
  c = gdImageColorAllocate(img,255,0,0);
  gdImageOpenPolygon(img,v,33,c);

  /* Output results to file */
  printf("Saving...\n");
  if (!(outfile=fopen(argc[2],"w"))) {
    return printf("Can't open <%s> for writing\n",argc[2]);
  }
  gdImageJpeg(img,outfile,85);
  fclose(outfile);
  gdImageDestroy(img);
  printf("Finished\n");
  return 0;
}

หมายเหตุ: Markdown messed up เชื่อมโยงของฉันในความคิดเห็นดังนั้นฉันจะชี้ให้เห็นว่ารหัสที่ใช้ในการแบ่งกลุ่มเพื่อแจ้งทุกพื้นที่ของสีแดงในภาพแล้วดึงวงกลมรอบที่ใหญ่ที่สุดของเหล่านี้ ตัวอย่างเช่นภาพนี้ :

ถังสีแดงและจอบบนชายหาด

สร้างเอาต์พุตต่อไปนี้:

ถังสีแดงมีวงกลมล้อมรอบเพราะมันใหญ่กว่าโพดำ


1
งานที่ดี! ;) ไปอีกด้วยธีมของการวาดพวกเขาเพื่อเน้นบางสิ่งบางอย่าง แต่ฉันอยากรู้ว่ามันจะทำอย่างไรถ้ามีวัตถุสีแดงสองชิ้น ... ? (+1)
Doorknob

2
มันแปลงพื้นที่สีแดงทั้งหมดเป็นส่วนที่แตกต่างกันและเลือกที่ใหญ่ที่สุด ตัวอย่างเช่นในรูปภาพของที่ฝากข้อมูลสีแดงและสเปดที่ฝากข้อมูลนี้ชนะ นี่คือผลลัพธ์
squeamish ossifrage

10

มาติกา

ClearAll[f]
f[image_,rad_, xPos_:.5,yPos_:.5,color_:Darker[Red,0.3],thick_:.01,axes_:False]:=
 Module[{i=ImageDimensions[image],rr,y=SeedRandom[2]},
 rr:=RandomReal[{-.1,.1}];
 Show[image,Graphics[{color,JoinForm["Round"],CapForm["Round"],Thickness[thick],
 Line[t=Table[{rad i[[2]] (Cos[z]+rr)+i[[1]]xPos,rad i[[2]] (Sin[z]+rr)+i[[2]] yPos},
 {z,0, 2 Pi+2Pi/12,Pi/12}]]}],Axes-> axes]]

f ใช้พารามิเตอร์ต่อไปนี้:

  • image: รูปภาพที่จะถูกทำเครื่องหมายด้วยวงกลม
  • rad: รัศมีของวงกลมในส่วนของความกว้างของภาพ
  • xPos: ตำแหน่งของศูนย์กลางของวงกลมตาม x จาก 0 ถึง 1 (ค่าเริ่มต้น = .5)
  • yPos: ตำแหน่งของศูนย์กลางของวงกลมตาม y จาก 0 ถึง 1 (ค่าเริ่มต้น = .5)
  • สี: สีหมึก (ค่าเริ่มต้น = สีแดงเข้ม)
  • ความหนา: ความหนาของเส้นขีด (ค่าเริ่มต้น = .01)
  • แกน: ว่าจะแสดงแกน (ค่าเริ่มต้น = เท็จ)

ตัวอย่าง

text = Import["text.png"]
f[text,.13,.58,.23]

pic1

รัศมีที่แตกต่างสถานที่ตั้งสีฟ้าจังหวะหนาแสดงแกน

f[text,.22,.7,.5,Blue,.015,True]

pic2


ว้าวดีมาก! เป็นแบบสุ่มนี้หรือไม่? (ต้องสร้างเอาต์พุตเดียวกันสำหรับอินพุตเดียวกัน)
Doorknob

ฉันใช้การสุ่มเพื่อเบี่ยงเบนจากวงกลมจริง ฉันคิดว่ามันโอเค ถ้าไม่ฉันสามารถ hardwire รูปร่าง
DavidC

"ต้องสามารถคาดเดาได้เช่นอินพุตภาพเดียวกันจะต้องส่งออกผลลัพธ์เดียวกันคุณสามารถใช้การสุ่มได้ แต่ผลลัพธ์จะต้องสอดคล้องกับอินพุตเดียวกัน" ต้องมีวิธีในการรับ RNG ที่เป็นเมล็ดใน Mathematica ใช่ไหม
Doorknob

ใช่SeedRandomดูเหมือนว่าจะทำเคล็ดลับ
DavidC

ดีมาก! +1
Doorknob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.