이미지의 색상 추적


17

이 스택 스 니펫에 이미지를로드하고 이미지 위로 마우스를 이동하십시오. 커서 지점에서 시작 하여 색조 각도 를 따르는 검은 곡선이 그려집니다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><style>canvas{border:1px solid black;}</style>Load an image: <input type='file' onchange='load(this)'><br><br>Max length <input id='length' type='text' value='300'><br><br><div id='coords'></div><br><canvas id='c' width='100' height='100'>Your browser doesn't support the HTML5 canvas tag.</canvas><script>function load(t){if(t.files&&t.files[0]){var e=new FileReader;e.onload=setupImage,e.readAsDataURL(t.files[0])}}function setupImage(t){function e(t){t.attr("width",img.width),t.attr("height",img.height);var e=t[0].getContext("2d");return e.drawImage(img,0,0),e}img=$("<img>").attr("src",t.target.result)[0],ctx=e($("#c")),ctxRead=e($("<canvas>"))}function findPos(t){var e=0,a=0;if(t.offsetParent){do e+=t.offsetLeft,a+=t.offsetTop;while(t=t.offsetParent);return{x:e,y:a}}return void 0}$("#c").mousemove(function(t){function e(t,e){var a=ctxRead.getImageData(t,e,1,1).data,i=a[0]/255,r=a[1]/255,o=a[2]/255;return Math.atan2(Math.sqrt(3)*(r-o),2*i-r-o)}if("undefined"!=typeof img){var a=findPos(this),i=t.pageX-a.x,r=t.pageY-a.y;$("#coords").html("x = "+i.toString()+", y = "+r.toString());var o=parseInt($("#length").val());if(isNaN(o))return void alert("Bad max length!");for(var n=[i],f=[r],h=0;n[h]>=0&&n[h]<this.width&&f[h]>=0&&f[h]<this.height&&o>h;)n.push(n[h]+Math.cos(e(n[h],f[h]))),f.push(f[h]-Math.sin(e(n[h],f[h]))),h++;ctx.clearRect(0,0,this.width,this.height),ctx.drawImage(img,0,0);for(var h=0;h<n.length;h++)ctx.fillRect(Math.floor(n[h]),Math.floor(f[h]),1,1)}});</script>

이 스 니펫은 Chrome에서만 테스트했습니다.

예를 들어, 커서가 빨간색 위에 있으면 곡선의 기울기가 0 °이지만 노란색 위에 있으면 60 °의 기울기가 있습니다. 곡선은 지정된 길이 동안 계속 진행되어 색조와 일치하도록 기울기를 계속 변경합니다.

이 이미지를로드하고 커서를 이미지 위로 이동하면 커서 주위의 선이 시계 반대 방향으로 완전히 회전합니다.

색조 각도

이것이것은 시도 할 다른 깔끔한 이미지입니다. (저장 한 다음 스 니펫으로로드해야합니다. 출처 간 제약으로 인해 직접 연결할 수 없습니다.)

다음은 스 니펫의 축소되지 않은 버전입니다.

도전

스 니펫이 수행하는 작업을 수행하는 프로그램을 대화식이 아닌 작성하십시오. 이미지 경계에서 이미지와 (x, y) 좌표와 최대 커브 길이를 가져옵니다. (x, y)에서 시작하여 색조 각도를 따라 최대 길이에 도달하거나 이미지 경계에 도달하면 끝나는 검은 색 곡선이 추가 된 동일한 이미지를 출력합니다.

구체적으로, (x, y)에서 커브를 시작하고 거기에서 색조 각도를 측정합니다. 새 위치가 정수 좌표가 아닐 가능성이 있으므로 해당 방향으로 한 단위 (한 픽셀 너비)로 이동 하십시오 . 곡선의 다른 점을 표시하고 (같은 것을 사용하여 가장 가까운 픽셀의 색상을 사용하여, 다시 이동 floor하거나 round, 내가 정확하게이 확인되지 않습니다). 커브가 범위를 벗어나거나 최대 길이를 초과 할 때까지 이와 같이 계속하십시오. 완료하려면 모든 곡선 점을 이미지에 겹친 단일 검은 색 픽셀 (다시 가장 가까운 픽셀 사용)로 플로팅하고이 새 이미지를 출력합니다.

"hue angle"은 단지 색조입니다 .

hue = atan2(sqrt(3) * (G - B), 2 * R - G - B)

기술적으로 색조가없는 그레이 스케일 값의 경우 0을 반환하지만 괜찮습니다.

(이 공식은 atan2대부분의 내장 수학 라이브러리를 사용합니다. R, G, B는 0에서 255가 아닌 0에서 1 사이입니다.)

  • 이미지 라이브러리뿐만 아니라 일반적인 무손실 이미지 파일 형식을 사용할 수 있습니다.
  • stdin 또는 명령 행에서 입력을 받거나 이미지 파일 이름, x 및 y에 대한 인수 및 최대 길이를 가진 함수를 작성하십시오.
  • 최대 길이와 x 및 y는 항상 음이 아닌 정수입니다. x와 y가 범위 내에 있다고 가정 할 수 있습니다.
  • 출력 이미지를 원하는 이름으로 저장하거나 간단히 표시하십시오.
  • 구현이 스 니펫과 정확히 일치 할 필요는 없습니다. 약간 다른 반올림 / 계산 방법으로 인해 약간 다른 곳에서 몇 픽셀이 좋습니다. 혼란스런 경우 곡선이 크게 달라 지지만 시각적으로보기 만하면 괜찮습니다.

채점

바이트 단위 의 가장 작은 제출 이깁니다.


1
스 니펫은 Firefox에서 완전히 손상되었습니다.
Ypnypn

스 니펫은 Safari에서도 작동하지 않습니다. (하지만 멋진 도전, +1)
Alex A.

@ Calvin 's Hobbies 채팅해도 될까요? chat.stackexchange.com/rooms/22029/…
BrainSteel

답변:


2

MATLAB, 136

function t(g,x,y,l)
m=imread(g);imshow(m); h=2*pi*rgb2hsv(m);h=h(:,:,1);s=streamline(cos(h),-sin(h),x,y,[1,l]);set(s,'LineW',1,'Co','k');

@sanchises에서 대부분의 설정을 복사했지만 streamline경로를 계산하고 그리는 데 사용합니다. 그러나 라인을 앤티 앨리어싱하고 지정된 가장 가까운 이웃이 아닌 쌍 선형 보간을 사용합니다.


5

SDL이있는 C, 549516 바이트

이 파티를 시작하겠습니다! 어떤 이유로, 나는 오늘 밤 골프에서 내 손을 시험 해보고 싶다고 느꼈다. 너희들이하는 일은 어렵다 ... 내가이 사이트에서 아무것도 보지 못한 것이 있다면 SDL이다. 방금 이유를 알았을 것입니다. 이 특정 스 니펫은 SDL2 및 SDL1.2를 모두 준수하지만 끔찍합니다. 처럼 호출 f("imagename.bmp", xcoord, ycoord, max_length);됩니다. 인수에 지정된 것과 동일한 이름의 파일을 저장합니다. 결과는 OP의 코드 스 니펫과 매우 유사하지만 "후지산"입니다. 나중에이 문제를 해결하려고 할 수 있습니다.

#include"SDL.h"
f(char*C,x,y,m){SDL_Surface*P=SDL_LoadBMP(C);int p=P->pitch,i=P->format->BytesPerPixel,q=0;double X=x,Y=y,f=255,R,G,B,h;Uint8*Q,d=1,r,g,b,k;while(d){Q=P->pixels+y*p+i*x;SDL_GetRGB(i==4?*(Uint32*)Q:i==3?SDL_BYTEORDER==4321?*Q<<16|Q[1]<<8|Q[2]:*Q|Q[1]<<8|Q[2]<<16:i==2?*(Uint16*)Q:*Q,P->format,&r,&g,&b);R=r/f;G=g/f;B=b/f;h=atan2(sqrt(3)*(G-B),2*R-G-B);for(k=0;k<i;k++)Q[k]=0;X+=cos(h);Y-=sin(h);if((int)X-x|(int)Y-y)q++;x=X;y=Y;d=x<0|x>=P->w|y<0|y>=P->h|q>=m?0:1;}SDL_SaveBMP(P,C);SDL_FreeSurface(P);}

여기에 모든 것이 풀려 있습니다.

#include"SDL.h"
f(char*C,x,y,m){
    SDL_Surface*P=SDL_LoadBMP(C);
    int p=P->pitch,i=P->format->BytesPerPixel,q=0;
    double X=x,Y=y,f=255,R,G,B,h;
    Uint8*Q,d=1,r,g,b,k;
    while(d){
        Q=P->pixels+y*p+i*x;
        SDL_GetRGB(i==4?*(Uint32*)Q:i==3?SDL_BYTEORDER==4321?*Q<<16|Q[1]<<8|Q[2]:*Q|Q[1]<<8|Q[2]<<16:i==2?*(Uint16*)Q:*Q,P->format,&r,&g,&b);
        R=r/f;
        G=g/f;
        B=b/f;
        h=atan2(sqrt(3)*(G-B),2*R-G-B);
        for(k=0;k<i;k++)Q[k]=0;
        X+=cos(h);
        Y-=sin(h);
        if((int)X-x|(int)Y-y)q++;
        x=X;y=Y;
        d=x<0|x>=P->w|y<0|y>=P->h|q>=m?0:1;
    }
    SDL_SaveBMP(P,C);
    SDL_FreeSurface(P);
}

솔직히 말해서 플랫폼을 교차로 만들려면주의를 기울여야한다는 점에 유의해야합니다. 정직하게 말하면, 상당한 수의 바이트를 삭감하더라도 내 컴퓨터에 하드 코딩하는 것은 좋지 않습니다. 아직도, 나는 여기에 몇 가지 불필요한 것들이 있다고 생각하고 나중에 다시 살펴볼 것입니다.

편집하다-------

이 IS 그래픽 출력은 결국 ... 정기적으로 흥미로운 이미지로 업데이트하겠습니다.

f("HueTest1.bmp", 270, 40, 200);

HueTest1.bmp

f("HueTest2.bmp", 50, 50, 200);

HueTest2.bmp

f("HueTest3.bmp", 400, 400, 300);

HueTest3.bmp


3

파이썬 203 172

from scipy.misc import*
def f(i,x,y,l):
 a=imread(i);Y,X,_=a.shape;o=a.copy()
 while(X>x>0<y<Y<[]>l>0):r,g,b=a[y,x]/255.;o[y,x]=0;l-=1;x+=2*r-g-b;y-=3**.5*(g-b);imsave(i,o)

샘플 출력 : 여기에 이미지 설명을 입력하십시오

와 전화 f("image.jpg", 400, 400, 300)

누군가가 그것을 개선 할 제안이 있다면 가져 오기 위해 많은 문자를 낭비했습니다. 3.0에서 작동하지 않을 수 있습니다


한 눈에보기 : sqrt(3) -> 3**.5? 수입품에 대해서는 아무것도 생각할 수 없습니다.
Sp3000

좋은 것! 앞으로 유용 할 것입니다.
grovesNL

3

MATLAB, 186 172

게임이 시작 되었습니다 ! 호출로 t('YourImage.ext',123,456,100')(100)의 초기 위치가 될 수없는 타입 MATLAB 지지체의 화상에 대한 (X, Y) = (123,456)과 최대 길이부터 바로 오른쪽과 아래쪽 가장자리 정도로하는 것이 (즉, 저 2 바이트를 요할 것) 가장자리에서 x=799.99시작하고에서 시작 하는 것과 같은 것을 사용하십시오 x=800. 인덱싱은 0이 아닌 1에서 시작합니다.

암호:

function t(g,x,y,l)
m=imread(g);[Y,X,~]=size(m);h=2*pi*rgb2hsv(m);while(x>0&x<X&y>0&y<Y&l)
p=ceil(x);q=ceil(y);m(q,p,:)=0;a=h(q,p);x=x+cos(a);y=y-sin(a);l=l-1;end
imshow(m)

개정 :

  • 라인이 픽셀보다 길지 않기 때문에 이전 픽셀에서 다음 픽셀로 줄을 바 꾸었습니다. 그것이 픽셀을 생성하는 것으로 알고있는 가장 짧은 코드이기 때문에 여전히 사용 line하고 있습니다.
  • 사용, 파란색 검은 색에서 색을 변경 Co에 확대 Color(MATLAB에서 자동 않습니다)
  • @grovesNL 덕분에 다음 위치를 계산하고 점을 그리는 순서가 변경되어 위치를 변경 한 경계 확인했기 때문에 실제로 범위를 벗어났습니다 .
  • 선 그리기에서 RGB 매트릭스를 0으로 설정하고 이후에 표시하도록 변경되었습니다.

검은 선 사탕


유효 하지 x=0않거나 y=0잠재적으로 유효합니까?
grovesNL

또한이 166 바이트는 어떻습니까?
grovesNL

@grovesNL 죄송합니다. 실수로 function헤더 없이 테스트 버전을 계산했습니다 . 사양은 내가 그래서, MATLAB의 한 기반을 사용하고 있으므로, 제로 또는 1 기반 색인을 필요로하지, 않았 x=0거나 y=0이 프로그램에 유효하지 않습니다.
Sanchises

아, MATLAB이 1 기반이라는 것을 잊었습니다. 그러나 그것이 대신 만들어 x=X지고 y=Y유효 할 수 있다고 생각 합니까?
grovesNL

1
하! 본인의 게임에서 이길 수 있습니다. MATLAB 솔루션 은 135 자입니다!
AJMansfield

1

처리, 323 자

void h(String f,float x,float y,float m){PImage i=loadImage(f);PImage i2=loadImage(f);while(m>0){color c=i.get((int)x,(int)y);float r=red(c)/255;float g=green(c)/255;float b=blue(c)/255;float h=atan2(sqrt(3)*(g-b),2*r-g-b);float dx=cos(h);float dy=-sin(h);m-=1;x+=dx;y+=dy;i2.set((int)x,(int)y,color(0));}i2.save("o.png");}

공백으로 :

void h(String f, float x, float y, float m) {
  PImage i = loadImage(f);
  PImage i2 = loadImage(f);

  while (m > 0) {

    color c = i.get((int)x, (int)y);
    float r = red(c)/255;
    float g = green(c)/255;
    float b = blue(c)/255;
    float h = atan2(sqrt(3) * (g - b), 2 * r - g - b);

    float dx = cos(h);
    float dy = -sin(h);

    m-= 1;
    x += dx;
    y += dy;

    i2.set((int)x, (int)y, color(0));
  }

  i2.save("o.png");
}

색조 추적 이미지

나는 이것을 더 짧게 할 수 있다고 확신하지만 지금은 효과가 있습니다.


0

자바 스크립트 414

function P(G,x,y,l){
I=new Image()
I.onload=function(){d=document,M=Math,C=d.createElement('canvas')
d.body.appendChild(C)
w=C.width=I.width,h=C.height=I.height,X=C.getContext('2d')
X.drawImage(I,0,0)
D=X.getImageData(0,0,w,h),d=D.data,m=255,i=0
for(;l--;i=(w*~~y+~~x)*4,r=d[i]/m,g=d[i+1]/m,b=d[i+2]/m,H=M.atan2(M.sqrt(3)*(g-b),2*r-g-b),d[i]=d[i+1]=d[i+2]=0,x+=M.cos(H),y-=M.sin(H))
X.putImageData(D,0,0)}
I.src=G}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.