Truy tìm màu sắc của một hình ảnh


17

Tải một hình ảnh vào đoạn trích ngăn xếp này và di chuyển chuột của bạn qua nó. Một đường cong màu đen theo góc màu , bắt đầu từ điểm con trỏ của bạn, sẽ được vẽ:

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

Tôi chỉ thử đoạn trích này trong Google Chrome.

Ví dụ: khi con trỏ ở trên màu đỏ, đường cong có độ dốc 0 °, nhưng khi nó ở trên màu vàng, nó có độ dốc 60 °. Đường cong tiếp tục cho độ dài quy định, liên tục thay đổi độ dốc của nó để phù hợp với màu sắc.

Tải hình ảnh này lên và khi bạn xoay con trỏ qua nó, đường chỉ quanh con trỏ sẽ thực hiện lần lượt hoàn toàn ngược chiều kim đồng hồ:

góc màu

Cái nàycái này là những hình ảnh gọn gàng khác để thử. (Bạn sẽ cần lưu chúng và sau đó tải chúng bằng đoạn mã. Chúng không thể được liên kết trực tiếp do các ràng buộc về nguồn gốc chéo.)

Đây là phiên bản rút gọn của đoạn trích:

Thử thách

Viết chương trình thực hiện những gì đoạn trích đang làm, chỉ là không tương tác. Lấy một hình ảnh và tọa độ (x, y) trong giới hạn của hình ảnh và độ dài đường cong tối đa. Xuất ra cùng một hình ảnh với đường cong màu đen được thêm vào theo các góc màu bắt đầu từ (x, y) và kết thúc khi nó đạt đến độ dài tối đa hoặc chạm vào một ranh giới hình ảnh.

Cụ thể, bắt đầu đường cong tại (x, y) và đo góc màu ở đó. Đi một đơn vị (chiều rộng một pixel) theo hướng đó, lưu ý rằng vị trí mới của bạn rất có thể không phải là tọa độ nguyên . Đánh dấu một điểm khác trên đường cong và di chuyển lại, sử dụng màu sắc từ pixel gần nhất (sử dụng cái gì đó như floorhoặc round, tôi sẽ không kiểm tra chính xác điều này). Tiếp tục như vậy cho đến khi đường cong đi ra khỏi giới hạn hoặc nó vượt quá độ dài tối đa. Để kết thúc, vẽ tất cả các điểm đường cong dưới dạng các pixel đen đơn (một lần nữa, sử dụng các pixel gần nhất) phủ lên hình ảnh và xuất hình ảnh mới này.

"Góc màu" chỉ là màu sắc :

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

Lưu ý rằng đối với các giá trị thang độ xám về mặt kỹ thuật không có màu sắc, giá trị này trả về 0, nhưng điều đó tốt.

(Công thức này sử dụng atan2hầu hết các thư viện toán học tích hợp có. R, G, B là từ 0 đến 1, không phải từ 0 đến 255.)

  • Bạn có thể sử dụng bất kỳ định dạng tệp hình ảnh lossless phổ biến cũng như bất kỳ thư viện hình ảnh.
  • Lấy đầu vào từ stdin hoặc dòng lệnh hoặc viết hàm với các đối số cho tên tệp hình ảnh, x và y và độ dài tối đa.
  • Độ dài tối đa và x và y luôn là các số nguyên không âm. Bạn có thể giả sử x và y nằm trong phạm vi.
  • Lưu hình ảnh đầu ra với một tên của sự lựa chọn của bạn hoặc chỉ đơn giản là hiển thị nó.
  • Việc triển khai của bạn không nhất thiết phải khớp chính xác với đoạn trích. Một vài pixel ở những nơi hơi khác nhau do phương pháp làm tròn / tính toán hơi khác nhau là tốt. (Trong các trường hợp hỗn loạn, điều này có thể dẫn đến các đường cong cuối cùng khác biệt lớn, nhưng miễn là chúng nhìn chính xác, điều đó ổn.)

Chấm điểm

Đệ trình nhỏ nhất tính bằng byte thắng.


1
Đoạn mã bị hỏng hoàn toàn trong Firefox.
Ypnypn 15/03/2015

Đoạn trích cũng không hoạt động trong Safari. (Mặc dù thử thách thú vị, +1)
Alex A.

@ Sở thích của Calvin Chúng ta có thể trò chuyện không? chat.stackexchange.com/rooms/22029/iêu
BrainSteel 17/03/2015

Câu trả lời:


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');

Sao chép hầu hết các thiết lập và như vậy từ @sanchises, nhưng thay vào đó tôi sử dụng streamlineđể tính toán và vẽ đường dẫn. Mặc dù vậy, nó không phản kháng đường thẳng và sử dụng phép nội suy song tuyến, chứ không phải là lân cận gần nhất như được chỉ định.


5

C với SDL, 549 516 byte

Tôi sẽ bắt đầu bữa tiệc này! Vì một số lý do, tôi cảm thấy muốn thử sức mình ở sân golf tối nay. Những gì các bạn làm là khó khăn ... Nếu có một điều tôi không thấy bất kỳ điều gì trên trang web này, đó là SDL. Tôi có thể vừa tìm ra lý do tại sao. Đoạn mã đặc biệt này tuân thủ cả SDL2 và SDL1.2, nhưng rất tàn bạo. Gọi như thế f("imagename.bmp", xcoord, ycoord, max_length);. Nó lưu một tệp có cùng tên như được đưa ra trong các đối số. Đầu ra dường như rất giống với đoạn mã của OP, nhưng "mờ hơn". Tôi có thể cố gắng khắc phục điều này một chút sau.

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

Đây là tất cả làm sáng tỏ:

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

Tôi nên lưu ý rằng cần phải cẩn thận để làm cho nó trở nên đa nền tảng - vì lợi ích của sự trung thực, nó không cảm thấy tốt khi mã hóa cứng cho máy của tôi, ngay cả khi nó cắt đi một số lượng đáng kể byte. Tuy nhiên, tôi cảm thấy như một vài thứ không cần thiết ở đây, và tôi sẽ xem xét lại sau.

BIÊN TẬP-------

Cuối cùng, đây là kết quả đồ họa IS ... Tôi sẽ cập nhật những hình ảnh mà tôi thấy thú vị theo định kỳ.

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

Con trăn, 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)

Đầu ra mẫu: nhập mô tả hình ảnh ở đây

Gọi với f("image.jpg", 400, 400, 300)

Tôi đã lãng phí rất nhiều ký tự cho việc nhập, nếu có ai có đề xuất cải thiện nó. Có thể không hoạt động trong 3.0


Nhìn thoáng qua : sqrt(3) -> 3**.5? Tôi không thể nghĩ bất cứ điều gì cho hàng nhập khẩu mặc dù.
Sp3000

Đẹp quá Điều đó sẽ hữu ích trong tương lai.
grovesNL

3

MATLAB, 186 172

Trò chơi là trên ! Gọi là t('YourImage.ext',123,456,100'), đối với một hình ảnh thuộc bất kỳ loại MATLAB nào hỗ trợ, bắt đầu từ (x, y) = (123,456) và độ dài tối đa 100. Vị trí ban đầu không thể chính xác ở cạnh phải và cạnh dưới (điều đó sẽ khiến tôi mất hai byte), do đó, bắt đầu ở rìa, sử dụng một cái gì đó như x=799.99để bắt đầu tạix=800 . Lập chỉ mục bắt đầu từ 1, không phải 0.

Mã số:

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)

Sửa đổi:

  • Thay đổi từ dòng từ pixel trước sang pixel tiếp theo thành chỉ đặt một dấu chấm tại một pixel, vì dòng sẽ không bao giờ dài hơn pixel! Vẫn đang sử dụng linevì đó là mã ngắn nhất mà tôi biết để tạo pixel.
  • Đã thay đổi màu từ đen sang xanh, sử dụng Cođể mở rộng sang Color(MATLAB tự động thực hiện)
  • Thay đổi thứ tự tính toán vị trí tiếp theo và vẽ một điểm, vì tôi nhận ra nhờ @grovesNL mà tôi thực sự đã rút ra khỏi giới hạn kể từ khi tôi kiểm tra giới hạn sau khi thay đổi vị trí.
  • Thay đổi từ vẽ đường để đặt ma trận rgb thành 0 và hiển thị sau.

Kẹo đường đen


Không có x=0hoặc y=0có khả năng vị trí hợp lệ?
GrovesNL

Ngoài ra, 166 byte này như thế nào?
GrovesNL

@grovesNL Xin lỗi, vô tình đếm phiên bản thử nghiệm của tôi mà không có functiontiêu đề. Spec không yêu cầu lập chỉ mục dựa trên không hoặc dựa trên một, vì vậy tôi đang sử dụng MATLAB, dựa trên một, nên không, x=0hoặc y=0không hợp lệ trong chương trình này.
Sanchise

À, tôi quên rằng MATLAB là một nền tảng (đã được một thời gian). Nhưng tôi đoán rằng có thể làm x=Xy=Yhợp lệ thay thế?
grovesNL

1
Hừ! Đánh bại bạn trong trò chơi của riêng bạn, giải pháp MATLAB của tôi chỉ có 135 ký tự!
AJMansfield

1

Đang xử lý, 323 ký tự

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

Với khoảng trắng:

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

hình ảnh dấu vết

Tôi chắc chắn rằng tôi có thể rút ngắn điều này hơn nữa, nhưng nó hoạt động cho đến bây giờ.


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}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.