Cerchi rossi a mano libera


19

Su http://meta.stackoverflow.com , abbiamo alcuni meme per conto nostro. Uno di questi è Freehand Red Circles.

Vedi questo post :

Quindi, la sfida è,

puoi disegnare cerchi rossi a mano libera ... con il codice?

Ulteriori restrizioni:

  • Prenderai un'immagine come input e dovrai emetterla con l'aggiunta di un cerchio rosso a mano libera.
  • Deve essere prevedibile, ovvero lo stesso input di immagine deve produrre lo stesso output. È possibile utilizzare la casualità, ma i risultati devono essere coerenti per lo stesso input.
  • L'output deve essere esattamente la stessa immagine dell'input, ad eccezione del cerchio (nessun'altra alterazione).
  • Il cerchio rosso a mano libera deve apparire a mano libera (nessun cerchio perfetto!), Essere rosso (ovviamente) e in genere deve apparire come un cerchio (nessuna linea a spirale casuale).

Questo è un , quindi la risposta con il maggior numero di voti all'inizio di marzo 2014. Non esiste un obiettivo specifico, oltre ai "cerchi rossi a mano libera", quindi sii il più creativo possibile in modo da ottenere il maggior numero di voti! (Per essere il più imparziale possibile, voterò ogni risposta che segue le regole.)


11
Penso che questo abbia bisogno di un po 'più di chiarimenti. Dobbiamo a) disegnare un nient'altro che un cerchio su una semplice tela bianca, b) prendere un'immagine contenente testo e disegnare un cerchio attorno al blocco di testo oppure c) prendere un testo e creare un'immagine del testo con un girarci intorno?
primo

3
+1 a @primo. Inoltre, ci sono altre cose da considerare: se tutto ciò che dobbiamo fare è disegnare un cerchio, è lo stesso cerchio ogni volta o il programma deve essere in grado di disegnare cerchi diversi? E quei cerchi devono essere casualmente diversi, o in qualche modo specificato dall'input dell'utente? Il programma deve essere in grado di gestire l'input dell'utente, per determinare la dimensione o la forma del cerchio? Importa in quale formato si trova l'output dell'immagine o qualcuno potrebbe inventare qualche arte ASCII intelligente?
Iszi,

2
Penso che la risposta sia "questo è un concorso di popolarità, quindi stupisci i tuoi amici di code-golf"
McKay,

Non so cosa non sia chiaro su questa domanda. @Iszi: la parola chiave è a mano libera. Apri Paint o GIMP e disegna alcuni cerchi a mano libera, sembrano tutti uguali? Dalla descrizione e dal collegamento, sembra che tu debba tracciare dei cerchi attorno a qualcosa, il che implicherebbe X e Y e le dimensioni. Che importanza ha il formato di file che usi? Basta eseguirlo attraverso un convertitore se si desidera PNG, JPEG o altro.

Credo con McKay. Se vuoi molti voti positivi, disegna cerchi a mano libera casuali. Altrimenti, codifica la tua cerchia.
Hosch250,

Risposte:


13

C - circa 750 720 byte se spremuto *

Penso di aver inventato qualcosa che sembra abbastanza a mano libera.

  • inizia da un angolo casuale
  • disegna un cerchio completo più o meno un po '
  • usa una spessa linea ondulata (forse troppo ondulata!)
  • è personalizzabile cambiando un MAGICnumero

Compilare:

gcc -o freehand freehand.c -lm

Correre:

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

Esempio:

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

Prima:

Prima

Dopo:

Dopo

Codice:

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

* e usando Uper UNIFORMe MperMAGIC


25

Libreria C + GD

Invece di disegnare solo dei vecchi cerchi, ho pensato che sarebbe stato divertente trovare qualcosa di rosso nella foto e tracciare un cerchio attorno a quello.

Ecco alcuni esempi dei risultati ottenuti con un paio di foto da Wikimedia Commons :

cose rosse con cerchi che appaiono intorno a loro

Ed ecco il codice. Spero che sia un po 'disordinato, ma non troppo difficile da seguire:

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

Nota: Markdown ha incasinato il mio link nei commenti, quindi ti faccio solo notare che il codice utilizza la segmentazione per identificare tutte le aree di rosso nell'immagine, quindi traccia un cerchio attorno al più grande di questi. Ad esempio, questa immagine :

secchio rosso e vanga su una spiaggia

produce il seguente output:

il secchio rosso ha un cerchio attorno, perché è più grande della vanga


1
Bel lavoro! ;) Va di più con il tema di disegnarli per enfatizzare qualcosa. Ma sono curioso di sapere cosa farebbe se ci fossero due oggetti rossi ...? (+1)
Maniglia della porta

2
Converte tutte le aree rosse in diversi segmenti e sceglie la più grande. Quindi, ad esempio, in questa foto di un secchio rosso e una vanga , il secchio vince. Ecco il risultato
ossifrage squeamish

10

matematica

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 accetta i seguenti parametri:

  • immagine: l'immagine che verrà contrassegnata da un cerchio
  • rad: il raggio del cerchio, in frazione della larghezza dell'immagine
  • xPos: la posizione del centro del cerchio lungo x, da 0 a 1 (impostazione predefinita = 0,5)
  • yPos: la posizione del centro del cerchio lungo y, da 0 a 1 (impostazione predefinita = 0,5)
  • colore: colore dell'inchiostro (impostazione predefinita = rosso scuro)
  • spessore: spessore tratto (impostazione predefinita = 0,01)
  • assi: se visualizzare gli assi (impostazione predefinita = Falso)

Esempi

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

pic1

Un raggio diverso, posizione, colore blu, corsa più spessa, visualizzazione degli assi.

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

pic2


Wow molto bello! È casuale, però? (Deve produrre lo stesso output per lo stesso input.)
Maniglia

Ho usato la casualità per le deviazioni da un cerchio reale. Ho pensato che fosse ok. Altrimenti, posso fissare la forma.
DavidC,

"Deve essere prevedibile, ovvero lo stesso input di immagine deve generare lo stesso output. È possibile utilizzare la casualità, ma i risultati devono essere coerenti per lo stesso input." Deve esserci un modo per ottenere un RNG seminato in Mathematica, giusto?
Maniglia della porta

Sì, SeedRandomsembra fare il trucco.
DavidC,

Va bene, fantastico! +1
Maniglia della porta
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.