フリーハンドの赤い丸


19

上にわたりhttp://meta.stackoverflow.com、我々は我々自身のいくつかのミームを持っています。それらの1つは、フリーハンドの赤丸です。

この投稿を参照してください。

だから、挑戦は

コードでフリーハンドの赤い円を描くことができますか?

追加の制限:

  • あなたはかかります、画像を入力として、あなたはフリーハンド赤い丸の画像が出力を追加しなければなりません。
  • 予測可能である必要があります。つまり、同じ画像入力は同じ出力になる必要があります。ランダム性を使用できますが、結果は同じ入力に対して一貫している必要があります。
  • 出力は、円(他の変更なし)を除いて、入力とまったく同じ画像でなければなりません。
  • フリーハンドの赤い円は、フリーハンド(完全な円ではない)に見え、赤(明らかに)であり、一般に円のように見える(ランダムな波線がない)必要があります。

これはので、2014年3月の初めに最も多くの賛成票を投じた回答が勝ちます。「フリーハンドの赤い丸」以外の特定の目標はありませんので、できるだけ創造性を高めて、最も多くの賛成票を獲得してください!(可能な限り公平になるように、ルールに従う回答に賛成票を投じます。)


11
これにはもう少し説明が必要だと思います。a)無地の白いキャンバスに円だけを描く、b)テキストを含む画像を撮る、テキストブロックの周りに円を描く、またはc)テキストを撮って、テキストの画像を作成するその周りを回る?
primo

3
+1から@primo。また、考慮すべき他の事柄があります:円を描くことだけが必要な場合、毎回同じ円であるか、プログラムが異なる円を描くことができる必要があるか、それらの円はランダムに異なるだけであるか、または何らかの方法でユーザー入力によって指定されていますか?プログラムは、円のサイズまたは形状を決定するために、ユーザー入力をまったく処理できる必要がありますか?画像出力の形式は重要ですか、それとも誰かが巧妙なASCIIアートを思い付くことができますか?
イッツィ14年

2
答えは「これは人気コンテストだから、あなたのコードゴルフ仲間に感銘を与えること」だと思う
マッケイ14年

この質問について何が不明瞭なのかわかりません。@Iszi-キーワードはフリーハンドです。PaintまたはGIMPを開き、フリーハンドの円をいくつか描画しますが、それらはすべて同じように見えますか?説明とリンクから、何かの周りに円を描く必要があるように見えます。これは、XとYとサイズを意味します。使用するファイル形式は何ですか?PNG、JPEG、その他が必要な場合は、コンバーターを介して実行します。

私はマッケイと信じています。多くの賛成票が必要な場合は、ランダムなフリーハンド円を描きます。それ以外の場合は、サークルをハードコーディングします。
Hosch25014年

回答:


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

*およびUfor UNIFORMおよびMforの使用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
良くやった!;)何かを強調するためにそれらを描くというテーマにもっと行きます。しかし、2つの赤いオブジェクトがあった場合、どうなるのか興味があります...?(+1)
ドアノブ

2
すべての赤い領域を異なるセグメントに変換し、最大の領域を選択します。たとえば、この赤いバケツとスペードの写真では、バケツが勝ちます。結果は
次のとおりです

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:0から1までのxに沿った円の中心の位置(デフォルト= .5)
  • yPos:yに沿った円の中心の位置、0〜1(デフォルト= .5)
  • 色:インクの色(デフォルト=暗赤色)
  • 太さ:ストロークの太さ(デフォルト= .01)
  • 軸:軸を表示するかどうか(デフォルト= False)

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

pic1

異なる半径、位置、青色、太いストローク、軸の表示。

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

pic2


わあ、とてもいい!これはランダムですか?(同じ入力に対して同じ出力を生成する必要があります。)
ドアノブ

真円からの偏差にランダム性を使用しました。大丈夫だと思った。そうでない場合は、形状を配線できます。
DavidC 14

「予測可能でなければなりません。つまり、同じ画像入力は同じ出力になる必要があります。ランダム性を使用できますが、同じ入力に対して結果は一貫している必要があります。」MathematicaでシードされたRNGを取得する方法が必要ですよね?
ドアノブ

はい、SeedRandomトリックをするようです。
DavidC 14

よし、すごい!+1
ドアノブ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.