Odręczne czerwone kółka

19

Na stronie http://meta.stackoverflow.com mamy kilka własnych memów. Jednym z nich jest Freehand Red Circles.

Zobacz ten post :

Wyzwaniem jest więc

umiesz rysować odręczne czerwone kółka ... z kodem?

Dodatkowe ograniczenia:

  • Jako obraz weźmiesz obraz i musisz go wydrukować z dodanym odręcznym czerwonym kółkiem.
  • Musi być przewidywalny, tzn. To samo wejście obrazu musi dawać takie samo wyjście. Możesz użyć losowości, ale wyniki muszą być spójne dla tych samych danych wejściowych.
  • Wyjście musi być dokładnie tym samym obrazem co wejście, z wyjątkiem koła (żadnych innych zmian).
  • Odręczne czerwone kółko musi wyglądać odręcznie (bez idealnych kół!), Być czerwone (oczywiście) i ogólnie wyglądać jak koło (bez losowych, kręconych linii).

To , więc wygra odpowiedź z największą popularnością na początku marca 2014 roku. Nie ma określonego celu, oprócz „czerwonych kółek odręcznych”, więc bądź tak kreatywny, jak to możliwe, aby uzyskać jak najwięcej pozytywnych opinii! (Aby być jak najbardziej obiektywnym, będę głosować za każdą odpowiedzią, która jest zgodna z zasadami).

Klamka
źródło
11
Myślę, że wymaga to nieco więcej wyjaśnień. Czy mamy: a) narysować tylko okrąg na zwykłym białym płótnie, b) zrobić zdjęcie zawierające tekst i narysować okrąg wokół bloku tekstu, lub c) wziąć tekst i stworzyć obraz tekstu za pomocą krążyć wokół niego?
primo
3
+1 do @primo. Ponadto należy wziąć pod uwagę inne rzeczy: jeśli wszystko, co musimy zrobić, to narysować okrąg, czy jest to ten sam okrąg za każdym razem, czy też program musi mieć możliwość rysowania różnych okręgów - i czy te okręgi mają być po prostu losowo różne, lub jakoś określone przez dane wejściowe użytkownika? Czy program musi w ogóle obsługiwać dane wejściowe użytkownika, aby określić rozmiar lub kształt koła? Czy to ważne, w jakim formacie jest wyjście obrazu, czy może ktoś wymyśli jakieś sprytne dzieło ASCII?
Iszi
2
Myślę, że odpowiedź brzmi: „to konkurs popularności, więc zaimponuj swoim kumplom golfa”
McKay,
Nie wiem, co jest niejasne w tym pytaniu. @Iszi - Kluczowym słowem jest odręczne. Otwórz Paint lub GIMP i narysuj kółka odręczne, czy wszystkie wyglądają tak samo? Z opisu i łącza wygląda na to, że musisz narysować okręgi wokół czegoś, co oznaczałoby X i Y oraz rozmiar. Jakie znaczenie ma używany format pliku? Wystarczy uruchomić konwerter, jeśli chcesz PNG, JPEG lub cokolwiek innego.
Wierzę w McKaya. Jeśli chcesz mieć dużo pozytywnych opinii, narysuj losowe kółka odręczne. W przeciwnym razie zakoduj swój krąg na
stałe

Odpowiedzi:

13

C - około 750 720 bajtów po ściśnięciu *

Myślę, że wymyśliłem coś, co wygląda dość odręcznie.

  • zaczyna się pod losowym kątem
  • rysuje pełne koło plus lub minus trochę
  • używa grubej, krętej linii (być może zbyt krętej!)
  • można dostosować, zmieniając MAGICliczbę

Skompilować:

gcc -o freehand freehand.c -lm

Biegać:

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

Przykład:

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

Przed:

Przed

Po:

Po

Kod:

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

* oraz korzystanie z Ufor UNIFORMi MforMAGIC


źródło
25

Biblioteka C + GD

Zamiast po prostu rysować koła w dowolnym miejscu, pomyślałem, że fajnie byłoby znaleźć coś czerwonego na zdjęciu i narysować koło wokół tego.

Oto kilka przykładów z wynikami uzyskanymi z ciągu kilku zdjęć z Wikimedia Commons :

czerwone rzeczy z okręgami pojawiającymi się wokół nich

A oto kod. Mam nadzieję, że jest trochę niechlujny, ale nie jest zbyt trudny do naśladowania:

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

Uwaga: Markdown pomieszał mój link w komentarzach, więc zaznaczę, że kod wykorzystuje segmentację do zidentyfikowania wszystkich obszarów czerwieni na obrazie, a następnie rysuje okrąg wokół największego z nich. Na przykład ten obraz :

czerwone wiadro i pik na plaży

produkuje następujące dane wyjściowe:

czerwone wiadro ma koło, ponieważ jest większe niż szpadel

piskliwy kostuch
źródło
1
Dobra robota! ;) Idzie bardziej z tematem ich rysowania, aby coś podkreślić. Ale jestem ciekawy, co by zrobił, gdyby były dwa czerwone obiekty ...? (+1)
Klamka
2
Konwertuje wszystkie czerwone obszary na różne segmenty i wybiera największy. Na przykład na tym zdjęciu czerwonego wiadra i łopaty wiadro wygrywa. Oto wynik
skrzypiące kostkowanie
10

Matematyka

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 przyjmuje następujące parametry:

  • image: obraz, który zostanie oznaczony okręgiem
  • rad: promień koła w ułamku szerokości obrazu
  • xPos: pozycja środka koła wzdłuż x, od 0 do 1 (domyślnie = .5)
  • yPos: pozycja środka koła wzdłuż y, od 0 do 1 (domyślnie = .5)
  • kolor: kolor tuszu (domyślnie = ciemnoczerwony)
  • grubość: grubość obrysu (domyślnie = 0,01)
  • osie: czy wyświetlać osie (domyślnie = Fałsz)

Przykłady

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

pic1

Inny promień, lokalizacja, kolor niebieski, grubszy obrys, wyświetlanie osi.

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

pic2

DavidC
źródło
Wow bardzo fajnie! Czy to jednak przypadek? (Musi generować tę samą moc wyjściową dla tego samego wejścia.)
Klamka
Użyłem losowości do odchyleń od prawdziwego koła. Myślałem, że to w porządku. Jeśli nie, mogę ustalić kształt.
DavidC
„Musi być przewidywalny, tzn. To samo wejście obrazu musi dawać taki sam wynik. Możesz użyć losowości, ale wyniki muszą być spójne dla tego samego wejścia”. Musi być jakiś sposób na zdobycie rozstawionego RNG w Mathematica, prawda?
Klamka
Tak, SeedRandomwydaje się , że załatwia sprawę.
DavidC
W porządku, świetnie! +1
Klamka