Від руки червоні кола


19

На сайті http://meta.stackoverflow.com ми маємо кілька власних мемів. Один з них - «Від руки червоних кіл».

Дивіться цю публікацію :

Отже, проблема полягає в тому,

ви можете намалювати від руки червоні кола ... з кодом?

Додаткові обмеження:

  • Ви будете приймати зображення як вхідне зображення , і ви повинні вивести його з додаванням червоного кола від руки.
  • Повинно бути передбачуваним, тобто один і той же вхід зображення повинен призводити до одного виводу. Можна використовувати випадковість, але результати повинні бути узгодженими для одного введення.
  • Вихід повинен бути точно таким же зображенням, як і вхідний, за винятком кола (жодних інших змін).
  • Червоне коло від руки повинно виглядати від руки (ніяких ідеальних кіл!), Бути червоним (очевидно) і виглядати загалом як коло (без випадкових чітко викладених ліній).

Це за , тому відповідь з найбільшою кількістю результатів на початок березня 2014 року виграє. Не існує жодної конкретної мети, окрім "від руки червоних кіл", тому будьте максимально креативними, щоб отримати максимальну кількість результатів! (Щоб бути максимально неупередженим, я підтримаю будь-яку відповідь, що відповідає правилам.)


11
Я думаю, це потребує дещо більшого уточнення. Ми: a) намалюйте нічого, крім кола, на простому білому полотні; б) зробіть зображення, що містить текст, і намалюйте коло навколо текстового блоку, або в) візьміть текст і створіть зображення тексту коло навколо нього?
прим

3
+1 до @primo. Крім того, є й інші речі, які слід враховувати: якщо все, що нам потрібно зробити, це намалювати коло, чи це кожен і той самий круг чи програма повинна вміти малювати різні кола - і чи є ці кола просто випадковими, або якимось чином вказано користувачем? Чи повинна програма взагалі вміти обробляти введення користувачів, визначати розмір або форму кола? Чи має значення, у якому форматі знаходиться зображення, чи хтось може просто придумати якесь розумне мистецтво ASCII?
Іссі

2
Я думаю, що відповідь - це конкурс на популярність, тому вражайте своїх приятелів з коду-гольфу
McKay

Я не знаю, що незрозуміло в цьому питанні. @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

Математика

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)
  • колір: колір чорнила (за замовчуванням = темно-червоний)
  • товщина: товщина ходу (за замовчуванням = .01)
  • осі: чи відображати осі (за замовчуванням = Неправильно)

Приклади

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.