手绘红色圆圈


19

http://meta.stackoverflow.com上,我们有一些模因。其中之一是手绘红色圆圈。

看到这个帖子

因此,挑战在于

可以用代码绘制手绘红色圆圈吗?

其他限制:

  • 您将以图像作为输入,并且必须在输出的图像上添加手绘红色圆圈。
  • 必须是可预测的,即相同的图像输入必须导致相同的输出。您可以使用随机性,但相同输入的结果必须一致。
  • 输出必须与输入完全相同的图像,除了带圆圈(没有其他更改)。
  • 徒手绘制的红色圆圈必须看起来徒手(没有完美的圆圈!),必须是红色的(显然),并且通常看起来像一个圆圈(没有随机的波浪线)。

这是一场,因此,在2014年3月开始投票最多的答案将获胜。除“手绘红色圆圈”外,没有其他具体目标,因此请尽可能发挥创意,以使您获得最多的投票!(为了尽可能保持公正,我将对遵循规则的所有答案进行投票。)


11
我认为这需要更多澄清。我们是要a)在纯白色画布上只画一个圆,b)拍摄一个包含文本的图像,然后在文本块周围画一个圆,或者c)拍摄一个文本,并用a创建一个文本图像绕圈吗?
2014年

3
+1到@primo。此外,还需要考虑其他事项:如果我们要做的只是画一个圆,是每次都画一个圆,还是程序需要能够绘制不同的圆?这些圆是随机不同的吗?或通过用户输入指定的方式?该程序是否需要完全能够处理用户输入以确定圆的大小或形状?图像输出采用哪种格式是否重要,或者有人可以提出一些聪明的ASCII艺术?
Iszi 2014年

2
我认为答案是“这是一场人气竞赛,请打动您的代码高尔夫伙伴”
McKay 2014年

我不知道这个问题尚不清楚。@Iszi-关键字是写意。打开Paint或GIMP并绘制一些徒手绘制的圆圈,它们看起来都一样吗?从描述和链接看来,您似乎必须在某些物体周围绘制圆圈,这意味着X&Y和大小。使用哪种文件格式有什么关系?如果需要PNG,JPEG或其他格式,只需通过转换器运行即可。

我相信麦凯。如果您需要大量支持,请绘制随机的手绘圆圈。否则,你的硬编码圈英寸
Hosch250

Answers:


13

Ç -约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用于UNIFORMM用于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弄乱了注释中的链接,因此我只想指出代码使用分段来识别图片中所有红色区域,然后在其中最大的区域上画一个圆圈。例如,此图像

红桶和锹在海滩上

产生以下输出:

红桶周围有一个圆圈,因为它比铁锹大


1
不错的工作!;)主题更多,吸引他们去强调一些东西。但是我很好奇,如果有两个红色物体会怎样...?(+1)
门把手

2
它将所有红色区域转换为不同的部分,并选择最大的部分。因此,例如在这张红色桶和小铲的照片中,桶获胜。结果就是
吱吱作响的ossifrage

10

Mathematica

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 采用以下参数:

  • 图片:将用圆圈标记的图片
  • rad:圆的半径,以图像宽度的分数表示
  • xPos:沿x的圆心位置,从0到1(默认值= .5)
  • yPos:沿y的圆心位置,从0到1(默认值= .5)
  • 颜色:墨水颜色(默认=深红色)
  • 厚度:笔触厚度(默认= 0.01)
  • axes:是否显示坐标轴(默认= False)

例子

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

图片1

不同的半径,位置,蓝色,较粗的笔划,显示轴。

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

图片2


哇,很棒!这是随机的吗?(必须为相同的输入产生相同的输出。)
门把手

我将随机性用于与真实圆的偏差。我以为还可以。如果没有,我可以硬连线形状。
DavidC 2014年

“必须是可预测的,即相同的图像输入必须产生相同的输出。可以使用随机性,但是对于相同的输入结果必须是一致的。” 必须有某种方法在Mathematica中获得种子RNG,对不对?
门把手

是的,SeedRandom似乎可以解决问题。
DavidC 2014年

好吧,太好了!+1
门把手
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.