Vòng tròn đỏ tự do


19

Trên http://meta.stackoverflow.com , chúng tôi có một vài meme của riêng mình. Một trong số đó là Vòng tròn đỏ Freehand.

Xem bài này :

Vì vậy, thách thức là,

bạn có thể vẽ các vòng tròn đỏ tự do ... bằng mã không?

Hạn chế bổ sung:

  • Bạn sẽ lấy một hình ảnh làm đầu vào và bạn phải xuất hình ảnh với vòng tròn màu đỏ tự do được thêm vào.
  • Phải dự đoán được, tức là cùng một hình ảnh đầu vào phải dẫn đến cùng một đầu ra. Bạn có thể sử dụng tính ngẫu nhiên, nhưng kết quả phải nhất quán cho cùng một đầu vào.
  • Đầu ra phải chính xác giống như hình ảnh đầu vào, ngoại trừ với vòng tròn (không có thay đổi nào khác).
  • Vòng tròn màu đỏ tự do phải trông tự do (không có vòng tròn hoàn hảo!), Màu đỏ (rõ ràng) và nhìn chung giống như một vòng tròn (không có đường uốn lượn ngẫu nhiên).

Đây là một , vì vậy câu trả lời có nhiều lượt hộ nhất vào đầu tháng 3 năm 2014 sẽ giành chiến thắng. Không có mục tiêu cụ thể nào, ngoài "vòng tròn đỏ tự do", vì vậy hãy sáng tạo nhất có thể để bạn nhận được nhiều sự ủng hộ nhất! (Để được thiên vị nhất có thể, tôi sẽ đưa ra bất kỳ câu trả lời nào tuân theo các quy tắc.)


11
Tôi nghĩ rằng điều này cần làm rõ hơn một chút. Chúng ta có phải a) vẽ không có gì ngoài một vòng tròn trên khung vẽ trắng đơn giản, b) lấy một hình ảnh có chứa văn bản và vẽ một vòng tròn xung quanh khối văn bản, hoặc c) lấy một văn bản và tạo một hình ảnh của văn bản bằng một vòng quanh nó?
Primo

3
+1 cho @primo. Ngoài ra, có những điều khác cần được xem xét: Nếu tất cả những gì chúng ta cần làm là vẽ một vòng tròn, thì đó có phải là cùng một vòng tròn mỗi lần hay chương trình cần có khả năng vẽ các vòng tròn khác nhau - và những vòng tròn đó chỉ là khác nhau ngẫu nhiên, hoặc bằng cách nào đó được chỉ định bởi đầu vào của người dùng? Chương trình có cần phải có khả năng xử lý đầu vào của người dùng không, để xác định kích thước hoặc hình dạng của vòng tròn? Có vấn đề gì ở định dạng đầu ra hình ảnh, hoặc ai đó có thể đưa ra một số nghệ thuật ASCII thông minh?
Iszi

2
Tôi nghĩ câu trả lời là "đây là một cuộc thi phổ biến, vì vậy hãy gây ấn tượng với những người bạn chơi golf mã của bạn"
McKay

Tôi không biết những gì không rõ ràng về câu hỏi này. @Iszi - Từ khóa là tự do. Mở Paint hoặc GIMP và vẽ một số vòng tròn tự do, tất cả chúng có giống nhau không? Từ mô tả và liên kết, có vẻ như bạn phải vẽ các vòng tròn xung quanh một cái gì đó, điều này sẽ bao hàm X & Y và kích thước. Bạn sử dụng định dạng tập tin nào? Chỉ cần chạy nó thông qua một trình chuyển đổi nếu bạn muốn PNG, JPEG hoặc bất cứ điều gì.

Tôi tin với McKay. Nếu bạn muốn có nhiều upvote, hãy vẽ các vòng tròn tự do ngẫu nhiên. Nếu không, hãy mã hóa vòng tròn của bạn trong.
Hosch250

Câu trả lời:


13

C - khoảng 750 720 byte nếu bị nén *

Tôi nghĩ rằng tôi đã nghĩ ra một cái gì đó có vẻ tự do đủ.

  • bắt đầu ở một góc ngẫu nhiên
  • vẽ một vòng tròn đầy đủ cộng hoặc trừ một chút
  • sử dụng một dòng nguệch ngoạc dày (có thể quá nguệch ngoạc!)
  • được tùy chỉnh bằng cách thay đổi một MAGIC số

Biên dịch:

gcc -o freehand freehand.c -lm

Chạy:

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

Thí dụ:

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

Trước:

Trước

Sau:

Sau

Mã số:

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

* và sử dụng Ucho UNIFORMMchoMAGIC


25

Thư viện C + GD

Thay vì chỉ vẽ những vòng tròn bất kỳ nơi nào cũ, tôi nghĩ sẽ rất vui nếu tìm thấy một cái gì đó màu đỏ trong bức tranh và vẽ một vòng tròn xung quanh đó.

Dưới đây là một số ví dụ về kết quả thu được với một vài hình ảnh từ Wikimedia Commons :

những thứ màu đỏ với những vòng tròn xuất hiện xung quanh chúng

Và đây là mã. Nó hơi lộn xộn, nhưng không quá khó để theo dõi, tôi hy vọng:

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

Lưu ý: Markdown đã làm rối liên kết của tôi trong các bình luận, vì vậy tôi sẽ chỉ ra rằng mã sử dụng phân đoạn để xác định tất cả các khu vực màu đỏ trong hình ảnh, sau đó vẽ một vòng tròn xung quanh phần lớn nhất trong số này. Ví dụ : hình ảnh này :

xô đỏ và thuổng trên bãi biển

tạo ra đầu ra sau:

cái xô màu đỏ có một vòng tròn bao quanh nó, bởi vì nó lớn hơn cái thuổng


1
Công việc tốt! ;) Đi nhiều hơn với chủ đề vẽ chúng để nhấn mạnh điều gì đó. Nhưng tôi tò mò về những gì nó sẽ làm nếu có hai vật thể màu đỏ ...? (+1)
Doorknob

2
Nó chuyển đổi tất cả các khu vực màu đỏ thành các phân khúc khác nhau và chọn lớn nhất. Vì vậy, ví dụ trong bức ảnh của một cái xô màu đỏ và thuổng , cái xô thắng. Đây là kết quả
ossifrage squeamish 4/214

10

Toán học

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 lấy các tham số sau:

  • hình ảnh: hình ảnh sẽ được đánh dấu bằng một vòng tròn
  • rad: bán kính của hình tròn, tính bằng phần chiều rộng của hình ảnh
  • xPos: vị trí tâm của đường tròn dọc theo x, từ 0 đến 1 (default = .5)
  • yPos: vị trí của tâm đường tròn dọc theo y, từ 0 đến 1 (default = .5)
  • màu: màu mực (mặc định = đỏ đậm)
  • độ dày: độ dày nét (mặc định = .01)
  • trục: có hiển thị trục hay không (default = false)

Ví dụ

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

pic1

Một bán kính khác nhau, vị trí, màu xanh lam, nét dày hơn, hiển thị các trục.

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

pic2


Wow, rất tuyệt! Đây có phải là ngẫu nhiên, mặc dù? (Nó phải tạo ra cùng một đầu ra cho cùng một đầu vào.)
Doorknob

Tôi đã sử dụng ngẫu nhiên cho các độ lệch từ một vòng tròn thực sự. Tôi nghĩ rằng đó là ok. Nếu không, tôi có thể cứng cáp hình dạng.
DavidC

"Phải có thể dự đoán được, tức là cùng một hình ảnh đầu vào phải dẫn đến cùng một đầu ra. Bạn có thể sử dụng tính ngẫu nhiên, nhưng kết quả phải nhất quán cho cùng một đầu vào." Phải có một số cách để có được một RNG hạt giống trong Mathicala, phải không?
Doorknob

Vâng, SeedRandomdường như để làm các mẹo.
DavidC

Được rồi, tuyệt! +1
Doorknob
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.