자유형 빨간색 원


19

에 걸쳐 http://meta.stackoverflow.com , 우리는 우리 자신의 몇 밈 있습니다. 그중 하나가 Freehand Red Circles입니다.

이 게시물 보기 :

따라서 도전은

코드로 자유형 빨간색 원을 그릴 수 있습니까?

추가 제한 사항 :

  • 당신은 걸릴 것 이미지를 입력으로, 당신은 자유 빨간색 원으로 이미지 출력에 추가해야합니다.
  • 예측 가능해야합니다. 즉, 동일한 이미지 입력은 동일한 출력을 가져야합니다. 임의성을 사용할 수 있지만 동일한 입력에 대해 결과가 일관되어야합니다.
  • 출력은 원을 제외하고 (다른 변경은 없음) 입력과 정확히 동일한 이미지 여야합니다.
  • 자유형 빨간색 원은 자유형 (완벽한 원 없음), 빨간색 (분명히), 일반적으로 원 모양 (임의의 구불 구불 한 선이 없음)이어야합니다.

이것은 이므로 2014 년 3 월 초에 가장 많은 투표를 한 답변이 이길 것입니다. "자유형 빨간색 원"외에는 구체적인 목표가 없으므로 최대한 창의성을 발휘하여 최대한 많은 찬성을 얻으십시오! (가능한 한 편견을 갖기 위해 규칙을 따르는 모든 답변을 찬성합니다.)


11
좀 더 설명이 필요하다고 생각합니다. a) 평범한 흰색 캔버스에 원을 그리면 안됩니다. b) 텍스트가 포함 된 이미지를 가져 와서 텍스트 블록 주위에 원을 그리거나 c) 텍스트를 가져 와서 텍스트로 이미지를 만듭니다. 주위에 동그라미?
primo

3
@primo +1 고려해야 할 다른 사항도 있습니다 : 원을 그리면됩니다. 매번 같은 원입니까, 아니면 프로그램이 다른 원을 그릴 수 있어야합니까? 또는 어떻게 든 사용자 입력으로 지정 되었습니까? 원의 크기 나 모양을 결정하기 위해 프로그램이 사용자 입력을 전혀 처리 할 수 ​​있어야합니까? 이미지 출력 형식이 중요합니까 아니면 누군가 영리한 ASCII 아트를 만들 수 있습니까?
Iszi

2
답은 "이것은 인기 콘테스트이므로 코드 골프 친구들에게 깊은 인상을 남길 것입니다"
McKay

이 질문에 대해 분명하지 않은 것이 무엇인지 모르겠습니다. @Iszi-핵심 단어는 자유입니다. 그림판 또는 김프를 열고 자유형 원을 그립니다. 모두 같습니까? 설명과 링크에서 X & Y와 크기를 의미하는 무언가 주위에 원을 그려야하는 것처럼 보입니다. 어떤 파일 형식을 사용하는 것이 중요합니까? PNG, JPEG 등을 원하는 경우 변환기를 통해 실행하십시오.

나는 맥케이를 믿습니다. 공감대를 많이 원한다면 자유 자유형 원을 그립니다. 그렇지 않으면 서클을 하드 코딩하십시오.
Hosch250

답변:


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

* 및 Ufor UNIFORMMfor 사용MAGIC


25

C + GD 라이브러리

오래된 곳에서 원을 그리는 대신 그림에서 빨간색을 찾아 그 주위에 원을 그리는 것이 재미있을 것이라고 생각했습니다.

여기에서 얻어진 결과의 몇 가지 예 사진 에서 위키 미디어 커먼즈 :

주위에 동그라미가 나타나는 붉은 색 물건

그리고 여기 코드가 있습니다. 약간 지저분하지만 따르기가 너무 어렵지 않습니다.

#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)
Doorknob

2
모든 빨간색 영역을 다른 세그먼트로 변환하고 가장 큰 영역을 선택합니다. 예를 들어 빨간 양동이와 스페이드 사진 에서 양동이가 이깁니다. 결과는 다음과 같습니다
squeamish ossifrage

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)
  • 좌표축 : 좌표축 표시 여부 (기본값 = False)

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

pic1

다른 반경, 위치, 파란색, 두꺼운 스트로크, 축 표시.

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

pic2


와우, 아주 좋아요! 그러나 이것은 무작위입니까? (동일한 입력에 대해 동일한 출력을 생성해야합니다.)
손잡이

실제 원과의 편차에 임의성을 사용했습니다. 나는 그것이 괜찮다고 생각했다. 그렇지 않으면 모양을 고정시킬 수 있습니다.
DavidC

"예측할 수 있어야합니다. 즉, 동일한 이미지 입력은 동일한 출력을 가져와야합니다. 임의성을 사용할 수 있지만 동일한 입력에 대해 결과가 일관되어야합니다." Mathematica에서 시드 RNG를 얻을 수있는 방법이 있어야합니까?
Doorknob

예, SeedRandom트릭을 수행하는 것 같습니다.
DavidC

좋아, 좋아! +1
Doorknob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.