Красные круги от руки


19

На сайте http://meta.stackoverflow.com у нас есть несколько собственных мемов. Один из них - Красные Круги от руки.

Смотрите этот пост :

Итак, проблема в том,

Вы можете нарисовать красные круги от руки ... с кодом?

Дополнительные ограничения:

  • Вы возьмете изображение в качестве ввода, и вы должны вывести изображение с добавленным красным кружком от руки.
  • Должен быть предсказуемым, то есть один и тот же ввод изображения должен давать одинаковый вывод. Вы можете использовать случайность, но результаты должны быть согласованы для одного и того же ввода.
  • На выходе должно быть точно такое же изображение, как на входе, за исключением кружка (без других изменений).
  • Красный круг от руки должен выглядеть от руки (без идеальных кругов!), Быть красным (очевидно) и выглядеть в общем как круг (без случайных волнистых линий).

Это , поэтому ответ с наибольшим количеством голосов в начале марта 2014 года победит. Никакой конкретной цели, кроме «красных кругов от руки», не существует, поэтому будьте настолько креативны, насколько это возможно, чтобы получить наибольшее количество голосов! (Чтобы быть максимально объективным, я буду приветствовать любой ответ, который следует правилам.)


11
Я думаю, что это требует немного большего уточнения. Должны ли мы: а) нарисовать не что иное, как круг на простом белом холсте, б) взять изображение, содержащее текст, и нарисовать круг вокруг текстового блока, или в) взять текст и создать изображение текста с обвести вокруг?
Прим

3
+1 к @primo. Кроме того, есть и другие вещи, которые необходимо учитывать: если все, что нам нужно сделать, это нарисовать круг, то ли это каждый раз один и тот же круг, или программа должна быть способна рисовать разные круги - и эти круги просто случайно различаются, или как-то указано пользовательским вводом? Должна ли программа вообще иметь возможность обрабатывать вводимые пользователем данные, чтобы определять размер или форму круга? Имеет ли значение, в каком формате выводится изображение, или кто-то может просто придумать какой-нибудь умный ASCII-арт?
Изи

2
Я думаю, что ответ «это соревнование в популярности, поэтому поразите своих друзей по коду-гольфу»
МакКей,

Я не знаю, что неясно в этом вопросе. @Iszi - ключевое слово от руки. Откройте Paint или GIMP и нарисуйте несколько кругов от руки, они все выглядят одинаково? Из описания и ссылки видно, что вы должны нарисовать круги вокруг чего-либо, что подразумевает X & Y и размер. Какое это имеет значение, какой формат файла вы используете? Просто запустите его через конвертер, если вы хотите PNG, JPEG или что-то еще.

Я верю в МакКея. Если вы хотите много голосов, нарисуйте случайные круги от руки. В противном случае жестко
закодируйте

Ответы:


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

Вместо того, чтобы просто рисовать круги в каком-то старом месте, я подумал, что было бы забавно найти что-то красное на картинке и нарисовать вокруг него круг.

Вот некоторые примеры результатов , полученных с через несколько фотографий из Wikimedia Commons :

красные вещи с кругами, появляющимися вокруг них

И вот код. Это немного грязно, но не слишком трудно следовать, я надеюсь:

#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
Он преобразует все красные области в разные сегменты и выбирает самые большие. Так, например, на этой фотографии красного ведра и лопаты ведро побеждает. Вот результат
брезгливое оссифраж

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)
  • оси: отображать ли оси (по умолчанию = False)

Примеры

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

pic1

Другой радиус, местоположение, синий цвет, более толстый ход, отображение осей.

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

pic2


Вау очень приятно! Хотя это случайно? (Он должен производить то же выход для того же входа.)
дверная ручка

Я использовал случайность для отклонений от истинного круга. Я думал, что это было хорошо. Если нет, я могу закрепить форму.
DavidC

«Должно быть предсказуемым, то есть один и тот же ввод изображения должен давать одинаковый вывод. Вы можете использовать случайность, но результаты должны быть согласованы для одного и того же ввода». Должен быть какой-то способ получить засеянный ГСЧ в Mathematica, верно?
Дверная ручка

Да, SeedRandomпохоже, делает свое дело.
DavidC

Хорошо, отлично! +1
дверная ручка
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.