FreeHand kırmızı daireler


19

Over http://meta.stackoverflow.com , biz kendi birkaç memlere var. Bunlardan biri Freehand Red Circles.

Bu gönderiye bakın :

Yani, zorluk şu ki,

el yapımı kırmızı daireler çizebilir misiniz?

Ek kısıtlamalar:

  • Bir görüntüyü giriş olarak alacaksınız ve görüntüyü serbest kırmızı daire eklenmiş olarak çıkarmalısınız.
  • Tahmin edilebilir olmalı, yani aynı görüntü girişi aynı çıktıyla sonuçlanmalıdır. Rasgelelik kullanabilirsiniz, ancak sonuçların aynı girdi için tutarlı olması gerekir.
  • Çıktı, daire haricinde, girdi ile tam olarak aynı görüntü olmalıdır (başka bir değişiklik yapılmamalıdır).
  • Serbest kırmızı daire serbest görünmeli (mükemmel daireler yok!), Kırmızı olmalı (açıkça) ve genellikle bir daire gibi görünmelidir (rastgele dalgalı çizgiler yok).

Bu bir , bu nedenle Mart 2014'ün başında en çok oy alan cevap kazanacaktır. "Serbest kırmızı daireler" dışında belirli bir hedef yoktur, bu yüzden mümkün olduğunca yaratıcı olun, böylece en çok oy al! (Mümkün olduğunca tarafsız olmak için, kurallara uyan herhangi bir cevabı iptal edeceğim.)


11
Bunun biraz daha açıklığa ihtiyacı olduğunu düşünüyorum. A) düz beyaz bir tuval üzerine bir daire dışında bir şey çizecek miyiz, b) metin içeren bir resim çekecek ve metin bloğunun çevresine bir daire çizecek miyiz veya c) bir metin alıp etrafında daire?
primo

3
@Primo'ya +1. Ayrıca, göz önünde bulundurulması gereken başka şeyler de var: Yapmamız gereken tek şey bir daire çizmekse, her seferinde aynı daire mi yoksa programın farklı daireler çizebilmesi gerekiyor mu - ve bu daireler rastgele farklı olabilir mi, veya bir şekilde kullanıcı girdisi ile belirtilsin mi? Dairenin boyutunu veya şeklini belirlemek için programın kullanıcı girişini işleyebilmesi gerekiyor mu? Görüntü çıkışının hangi formatta olduğu önemli mi, yoksa birisi sadece akıllı bir ASCII sanatı ortaya çıkarabilir mi?
Iszi

2
Bence cevap "bu bir popülerlik yarışması, bu yüzden kod golf arkadaşlarınızı etkileyin"
McKay

Bu soru hakkında neyin belirsiz olduğunu bilmiyorum. @Iszi - Anahtar kelime serbesttir. Paint veya GIMP'yi açın ve serbest daireler çizin, hepsi aynı mı görünüyor? Açıklama ve bağlantıdan, X & Y ve boyut anlamına gelen bir şeyin etrafına daireler çizmeniz gerekiyor gibi görünüyor. Hangi dosya biçimini kullandığınızın önemi nedir? PNG, JPEG veya başka bir şey istiyorsanız, bir dönüştürücü üzerinden çalıştırın.

McKay'e inanıyorum. Çok sayıda upvotes istiyorsanız, rastgele serbest daireler çizin. Aksi takdirde,
dairenizi

Yanıtlar:


13

C - sıkılırsa yaklaşık 750 720 bayt *

Sanırım yeterince serbest görünen bir şey buldum.

  • rastgele açıyla başlar
  • artı veya eksi biraz daire çizer
  • kalın dalgalı bir çizgi kullanır (belki çok dalgalı!)
  • bir MAGICsayı değiştirilerek özelleştirilebilir

Derleme:

gcc -o freehand freehand.c -lm

Çalıştırmak:

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

Misal:

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

Önce:

Önce

Sonra:

Sonra

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

* ve Uiçin UNIFORMve Miçin kullanmaMAGIC


25

C + GD kütüphanesi

Sadece eski herhangi bir yere daire çizmek yerine, resimde kırmızı bir şey bulmanın ve etrafına bir daire çizmenin eğlenceli olacağını düşündüm.

İşte elde edilen sonuçların bazı örnekler ile bir kaç fotoğraf arasından Wikimedia Commons :

çevrelerinde görünen kırmızı şeyler

Ve işte kod. Biraz dağınık, ama takip etmek çok zor değil, umarım:

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

Not: Markdown yorumlarda bağlantımı bozdu, bu yüzden kodun resimdeki tüm kırmızı alanlarını tanımlamak için segmentasyon kullandığını ve daha sonra bunların en büyüğünün etrafına bir daire çizdiğini göstereceğim . Örneğin, bu resim :

kırmızı kova ve kürek bir plajda

aşağıdaki çıktıyı üretir:

kırmızı kepçenin etrafında bir daire var, çünkü maçadan daha büyük


1
İyi iş! ;) Bir şeyi vurgulamak için onları çizme temasıyla daha çok şey gider. Ama iki kırmızı nesne olsaydı ne yapacağını merak ediyorum ...? (+1)
Kapı Tokmağı

2
Tüm kırmızı alanları farklı segmentlere dönüştürür ve en büyüğü seçer. Örneğin, bu kırmızı kova ve kürek fotoğrafında , kova kazanır. İşte sonuç
squeamish ossifrage

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 aşağıdaki parametreleri alır:

  • image: bir daire ile işaretlenecek resim
  • rad: görüntü genişliğinin kesirinde dairenin yarıçapı
  • xPos: 0'dan 1'e kadar dairenin merkezinin x boyunca konumu (varsayılan = .5)
  • yPos: dairenin merkezinin y boyunca konumu, 0'dan 1'e (varsayılan = .5)
  • renk: mürekkep rengi (varsayılan = koyu kırmızı)
  • kalınlık: strok kalınlığı (varsayılan = .01)
  • eksenler: eksenlerin görüntülenip görüntülenmeyeceği (varsayılan = Yanlış)

Örnekler

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

pic1

Farklı bir yarıçap, konum, mavi renk, kalın kontur, eksenleri görüntüleme.

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

pic2


Vay çok güzel! Bu rastgele mi? (Aynı giriş için aynı çıkışı üretmelidir.)
Kapı tokmağı

Gerçek bir çemberden sapmalar için rastgelelik kullandım. Tamam olduğunu düşündüm. Değilse, şekli zorlayabilirim.
DavidC

"Tahmin edilebilir olmalı, yani aynı görüntü girdisi aynı çıktıyla sonuçlanmalıdır. Rasgelelik kullanabilirsiniz, ancak sonuçların aynı girdi için tutarlı olması gerekir." Mathematica'da tohumlanmış bir RNG almanın bir yolu olmalı, değil mi?
Kapı tokmağı

Evet, SeedRandomhile yapıyor gibi görünüyor.
DavidC

Tamam, harika! +1
Kapı Tokmağı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.