ติดตามเฉดสีของรูปภาพ


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>

ฉันได้ทดสอบตัวอย่างนี้ใน Google Chrome เท่านั้น

ตัวอย่างเช่นเมื่อเคอร์เซอร์อยู่เหนือสีแดงเส้นโค้งจะมีความลาดเอียง 0 ° แต่เมื่ออยู่เหนือสีเหลืองมันจะมีความชัน 60 ° เส้นโค้งยังคงดำเนินต่อไปตามความยาวที่ระบุเปลี่ยนความชันของมันอย่างต่อเนื่องเพื่อให้เข้ากับสี

โหลดภาพนี้และเมื่อคุณเลื่อนเคอร์เซอร์ไปที่อื่นเส้นที่อยู่รอบเคอร์เซอร์ควรหมุนตามเข็มนาฬิกาจนสุด:

มุมสี

นี้และนี้เป็นภาพระเบียบอื่น ๆ ที่จะลอง (คุณจะต้องบันทึกพวกเขาแล้วโหลดด้วยข้อมูลโค้ดพวกเขาไม่สามารถเชื่อมโยงโดยตรงเนื่องจากข้อ จำกัด ข้ามที่มา)

นี่คือตัวอย่างข้อมูลย่อ:

ท้าทาย

เขียนโปรแกรมที่ทำในส่วนของ snippet แต่ไม่สามารถโต้ตอบได้ ถ่ายภาพและพิกัด (x, y) ในขอบเขตของภาพและความยาวโค้งสูงสุด เอาท์พุทภาพเดียวกันกับเส้นโค้งสีดำที่เพิ่มเข้ามาซึ่งเป็นไปตามมุมสีที่เริ่มต้นที่ (x, y) และสิ้นสุดลงเมื่อถึงความยาวสูงสุดหรือกระทบกับขอบภาพ

โดยเฉพาะเริ่มโค้งที่ (x, y) และวัดมุมสีที่มี ไปหนึ่งหน่วย (กว้างหนึ่งพิกเซล) ในทิศทางที่สังเกตว่าตำแหน่งใหม่ของคุณได้มากที่สุดไม่เป็นจำนวนเต็มประสานงาน ทำเครื่องหมายจุดอื่นบนเส้นโค้งแล้วเคลื่อนที่อีกครั้งโดยใช้เฉดสีจากพิกเซลที่อยู่ใกล้ที่สุด (ใช้บางอย่างเช่นfloorหรือroundฉันจะไม่ตรวจสอบสิ่งนี้อย่างแม่นยำ) ทำต่อไปเช่นนี้จนกว่าเส้นโค้งจะโค้งหรือเกินความยาวสูงสุด เมื่อต้องการเสร็จสิ้นให้พล็อตจุดโค้งทั้งหมดเป็นพิกเซลสีดำ (อีกครั้งใช้พิกเซลที่ใกล้ที่สุด) ซ้อนทับบนภาพและส่งภาพใหม่นี้

"มุมสี" เป็นเพียงเฉดสี :

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

โปรดทราบว่าสำหรับค่าระดับสีเทาที่ไม่มีเทคนิคสีจะส่งคืนค่า 0 แต่ไม่เป็นไร

(สูตรนี้ใช้atan2ว่าไลบรารีคณิตศาสตร์ในตัวส่วนใหญ่มี R, G, B มาจาก 0 ถึง 1 ไม่ใช่ 0 ถึง 255)

  • คุณสามารถใช้รูปแบบไฟล์ภาพ lossless ทั่วไปเช่นเดียวกับห้องสมุดภาพใด ๆ
  • รับอินพุตจาก stdin หรือบรรทัดคำสั่งหรือเขียนฟังก์ชันพร้อมอาร์กิวเมนต์สำหรับชื่อไฟล์รูปภาพ x และ y และความยาวสูงสุด
  • ความยาวสูงสุดและ x และ y เป็นจำนวนเต็มที่ไม่ใช่ค่าลบเสมอ คุณสามารถสมมติว่า x และ y อยู่ในช่วง
  • บันทึกภาพที่ส่งออกด้วยชื่อที่คุณเลือกหรือเพียงแค่แสดงมัน
  • การใช้งานของคุณไม่จำเป็นต้องตรงกับตัวอย่างทั้งหมด พิกเซลบางจุดในสถานที่ที่แตกต่างกันเล็กน้อยเนื่องจากวิธีการปัดเศษ / การคำนวณที่แตกต่างกันเล็กน้อยนั้นใช้ได้ (ในกรณีที่ยุ่งเหยิงสิ่งนี้อาจนำไปสู่ส่วนโค้งที่แตกต่างกันอย่างมาก แต่ตราบใดที่พวกเขามองเห็นถูกต้องมันก็ใช้ได้)

เกณฑ์การให้คะแนน

การส่งที่น้อยที่สุดในหน่วยไบต์ชนะ


1
ตัวอย่างข้อมูลใช้งานไม่ได้ใน Firefox
Ypnypn

ตัวอย่างยังไม่ทำงานใน Safari (แม้ว่าจะเป็นความท้าทายที่น่าสนใจ +1)
อเล็กซ์ A.

@ งานอดิเรกของ Calvin เราจะแชทกันได้ไหม? 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เพื่อคำนวณและวาดเส้นทาง มันทำ antialias บรรทัดแม้ว่าและใช้การแก้ไข bilinear มากกว่าเพื่อนบ้านที่ใกล้ที่สุดตามที่ระบุ


5

C กับ SDL 549 516 ไบต์

ฉันจะเริ่มปาร์ตี้นี้! ด้วยเหตุผลบางอย่างฉันรู้สึกอยากลองเล่นกอล์ฟในคืนนี้ สิ่งที่พวกคุณทำนั้นยาก ... หากมีสิ่งหนึ่งที่ฉันไม่เห็นในเว็บไซต์นี้มันเป็น SDL ฉันอาจจะเพิ่งพบว่าทำไม ตัวอย่างนี้สอดคล้องกับทั้ง SDL2 และ SDL1.2 แต่มีความเลวร้าย เรียกได้ว่าชอบf("imagename.bmp", xcoord, ycoord, max_length);เรียกว่าเหมือนมันจะบันทึกไฟล์ที่มีชื่อเดียวกับที่กำหนดไว้ในข้อโต้แย้ง ผลลัพธ์ดูเหมือนจะคล้ายกับข้อมูลโค้ดของ OP แต่เป็น "fuzzier" ฉันอาจพยายามแก้ไขในภายหลัง

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

ฉันควรทราบว่าใช้ความระมัดระวังในการทำให้ข้ามแพลตฟอร์ม - เพื่อประโยชน์ของความซื่อสัตย์มันไม่ได้รู้สึกดีที่จะ hardcode สำหรับเครื่องของฉันแม้ว่ามันจะตัดจำนวนไบต์จำนวนมากก็ตาม ถึงกระนั้นฉันก็รู้สึกเหมือนว่ามีบางสิ่งที่เกินความจำเป็นที่นี่และฉันจะดูอีกครั้งในภายหลัง

แก้ไข -------

นี่คือเอาท์พุทแบบกราฟิกหลังจากทั้งหมด ... ฉันจะอัปเดตด้วยภาพที่ฉันคิดว่าน่าสนใจเป็นระยะ

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

Python, 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')สำหรับรูปภาพประเภทใดก็ตามที่สนับสนุน MATLAB เริ่มต้นที่ (x, y) = (123,456) และความยาวสูงสุด 100 ตำแหน่งเริ่มต้นไม่สามารถอยู่ที่ขอบด้านขวาและขอบด้านล่างได้อย่างแม่นยำเริ่มต้นบนขอบใช้สิ่งที่ต้องการที่จะเริ่มต้นที่x=799.99 x=800การจัดทำดัชนีเริ่มต้นที่ 1 ไม่ใช่ 0

รหัส:

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ตั้งใจด้วยส่วนหัว Spec ไม่ต้องการการทำดัชนีแบบ zero-based หรือ one-based ดังนั้นฉันจึงใช้ MATLAB แบบอิงเดียวดังนั้นไม่x=0หรือy=0ไม่ถูกต้องในโปรแกรมนี้
Sanchises

อ่าฉันลืมไปว่า MATLAB เป็นระบบพื้นฐานเดียว (ใช้เวลาไม่นาน) แต่ผมเดาว่าอาจจะทำให้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

JavaScript 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.