2009-07-20 37 views
10

Tôi đang sử dụng XNA để xây dựng một dự án mà tôi có thể vẽ "graffiti" trên tường bằng máy chiếu LCD và máy ảnh đơn sắc được lọc để chỉ xem các con trỏ laser được giữ bằng tay. Tôi muốn sử dụng bất kỳ con trỏ laser nào - không thực sự quan tâm đến việc phân biệt chúng ở thời điểm này.Phát hiện chấm laser điểm ảnh nhanh

Bức tường là 10' x 10' , và camera chỉ là 640x480 vì vậy tôi cố gắng sử dụng đo lường sub-pixel sử dụng một đường cong spline như được nêu ở đây: camera tpub.com

này chạy ở 120fps (8 -bit), do đó, câu hỏi của tôi đối với tất cả các bạn là cách nhanh nhất để tìm trung tâm điểm laser điểm ảnh phụ đó. Hiện tại tôi đang sử dụng tìm kiếm 2D lực lượng vũ phu để tìm pixel sáng nhất trên hình ảnh (0 - 254) trước khi thực hiện phép nội suy spline. Phương pháp đó không phải là rất nhanh và mỗi khung hình mất nhiều thời gian hơn để máy tính được chuyển đến.

Chỉnh sửa: Cuối cùng, dữ liệu máy ảnh của tôi được biểu thị bằng một mảng byte 2D cho biết độ sáng pixel.

Điều tôi muốn làm là sử dụng trình đổ bóng XNA để tạo hình ảnh cho tôi. Điều đó có thực tế không? Từ những gì tôi hiểu, có thực sự không phải là một cách để giữ các biến liên tục trong một Pixel Shader như tổng số chạy, trung bình, v.v.

Nhưng vì lý do, chúng ta hãy tìm các pixel sáng nhất sử dụng vũ lực, sau đó lưu trữ chúng và các pixel lân cận của chúng cho đường cong spline vào X số đỉnh bằng cách sử dụng texcoords. Là thực tế sau đó sử dụng HLSL để tính toán một đường cong spline bằng cách sử dụng texcoords?

Tôi cũng mở các đề xuất bên ngoài hộp XNA của tôi, có thể là DX10/DX11, có thể một số loại FPGA, v.v. Tôi thực sự không có nhiều kinh nghiệm với cách xử lý dữ liệu theo cách này. Tôi tính nếu họ có thể làm một cái gì đó như thế này trên Wii-Mote sử dụng 2 pin AA hơn tôi có lẽ sẽ đi về điều này một cách sai lầm.

Bất kỳ ý tưởng nào?

+0

Điều gì làm chậm, thực hiện quét hoặc thực hiện nội suy spline sau đó? – Nosredna

+0

Nội suy spline là thành phần chậm nhất của nó, phụ thuộc vào vùng delta nào tôi đánh giá spline với. Trong trường hợp này, tôi muốn độ chính xác 0,1px. – bufferz

+0

Tôi nên thêm rằng nếu tôi có 20 laser, tính toán spline sẽ trở thành rất rất đắt tiền cPU khôn ngoan. – bufferz

Trả lời

3

Bạn đang xử lý một số phép toán khá phức tạp nếu bạn muốn độ chính xác của pixel phụ. Tôi nghĩ rằng this paper là điều cần cân nhắc. Thật không may, bạn sẽ phải trả tiền để xem nó bằng cách sử dụng trang web đó. Nếu bạn có quyền truy cập vào một thư viện phù hợp, họ có thể nắm giữ nó cho bạn.

Liên kết trong bài đăng gốc đề xuất thực hiện 1000 phép tính spline cho mỗi trục - nó được xử lý x và y độc lập, điều này phù hợp với hình ảnh tròn nhưng hơi lệch nếu hình ảnh là hình elip bị lệch. Bạn có thể sử dụng sau đây để có được một ước tính hợp lý:

x c = sum (x n .f (x n))/sum (f (x n))

trong đó x c là giá trị trung bình, x n là một điểm dọc theo trục x và f (x n) là giá trị tại điểm x n. Vì vậy, cho điều này:

  * 
     * * 
     * * 
     * * 
     * * 
     * * 
     * * * 
    * * * * 
    * * * * 
* * * * * * 
------------------ 
2 3 4 5 6 7 

cho:

sum (x n .f (x n)) = 1 * 2 + 3 * 3 + 4 * 9 + 5 * 10 + 6 * 4 + 7 * 1

sum (f (x n)) = 1 + 3 + 9 + 10 + 4 + 1

x c = 128/28 = 4,57

và lặp lại cho trục y.

+0

Điều này hoạt động khá tốt. Điều này chạy nhanh hơn tôi nhiều hơn so với thực hiện spline của tôi quá. Đó là khá nhiều thời gian thực! Cảm ơn vì đã góp ý. – bufferz

+0

Giới thiệu về liên kết: chỉ cần tìm kiếm tiêu đề. Lượt truy cập hàng đầu: http://groups.mrl.illinois.edu/granick/Publications/pdf%20files/2009/stephen_2009_image%20analysis%20with%20rapid%20and%20accurate%202d%20gaussian%20fit.pdf – jnm2

5

Nếu bằng cách Brute-buộc bạn có nghĩa là nhìn vào từng điểm ảnh một cách độc lập, về cơ bản đó là cách duy nhất để thực hiện nó. Bạn sẽ phải quét qua tất cả các điểm ảnh, bất kể bạn muốn làm gì với ảnh. Mặc dù bạn có thể không cần phải tìm các pixel sáng nhất, bạn có thể lọc hình ảnh theo màu (ví dụ: nếu bạn sử dụng laser đỏ). Điều này có thể dễ dàng thực hiện bằng cách sử dụng hình ảnh được mã hóa màu HSV. Nếu bạn đang tìm kiếm một số thuật toán nhanh hơn, hãy thử OpenCV. Nó được tối ưu hóa một lần nữa và một lần nữa để điều trị hình ảnh, và bạn có thể sử dụng nó trong C# thông qua một wrapper:

[http://www.codeproject.com/KB/cs/Intel_OpenCV.aspx][1]

OpenCV cũng có thể giúp bạn dễ dàng tìm thấy các trung tâm điểm và theo dõi từng điểm.

Có lý do nào khiến bạn đang sử dụng máy ảnh 120fps không? bạn biết con mắt của con người chỉ có thể nhìn thấy khoảng 30fps phải không? Tôi đoán nó sẽ theo các chuyển động laser rất nhanh ... Bạn có thể muốn xem xét việc kéo nó xuống, bởi vì xử lý thời gian thực 120fps sẽ rất khó để đạt được.

4

chạy qua 640 * 480 byte để tìm byte cao nhất sẽ chạy trong một ms. Ngay cả trên bộ vi xử lý chậm. Không cần phải đi theo con đường của shader.

Tôi khuyên bạn nên tối ưu hóa vòng lặp của mình. ví dụ: đây là rất chậm (bởi vì nó một phép nhân với tất cả các tra cứu mảng):

byte highest=0; 
foundX=-1, foundY=-1; 
for(y=0; y<480; y++) 
{ 
    for(x=0; x<640; x++) 
    { 
     if(myBytes[x][y] > highest) 
     { 
      highest = myBytes[x][y]; 
      foundX = x; 
      foundY = y; 
     } 
    } 
} 

này là nhanh hơn nhiều:

byte [] myBytes = new byte[640*480]; 
//fill it with your image 

byte highest=0; 
int found=-1, foundX=-1, foundY=-1; 
int len = 640*480; 
for(i=0; i<len; i++) 
{ 
    if(myBytes[i] > highest) 
    { 
     highest = myBytes[i]; 
     found = i; 
    } 
} 
if(found!=-1) 
{ 
    foundX = i%640; 
    foundY = i/640; 
} 

Đây là ra khỏi đỉnh đầu của tôi rất xin lỗi vì Các lỗi, ^)

3

Lực lượng vũ phu là cách thực sự duy nhất, tuy nhiên ý tưởng sử dụng trình đổ bóng là tốt - bạn sẽ giảm tải kiểm tra sức mạnh vũ phu từ CPU, chỉ có thể xem xét một số lượng nhỏ pixel đồng thời (khoảng 1 mỗi lõi), đến GPU, có khả năng có hơn 100 lõi câm (đường ống) có thể đồng thời so sánh các pixel (thuật toán của bạn có thể cần được sửa đổi một chút để hoạt động tốt với sự sắp xếp 1 lõi nhiều lệnh của GPU).

Vấn đề lớn nhất tôi thấy là liệu bạn có thể di chuyển dữ liệu đó đến GPU đủ nhanh hay không.

+0

Tôi làm cách nào để theo dõi pixel đơn lẻ cao nhất trên một khung trong GPU? Tôi có hiểu chính xác điều này ở chỗ các lõi câm không thể chia sẻ bộ nhớ theo cách có thể cho phép chúng so sánh pixel với pixel sáng nhất trước đó không? – bufferz

+1

GPU có thể được coi là một bộ sưu tập lớn các CPU thực sự đơn giản được tối ưu hóa cho các phép toán. Điểm khác biệt lớn nhất là bộ giải mã lệnh đã bị loại bỏ - một bộ điều khiển đơn gửi cùng một lệnh tới từng lõi câm, nơi nó được thực hiện trên phần dữ liệu lõi đó. Các câu lệnh IF được thực hiện bằng cách chạy cùng một mã hai lần - thay vì phân nhánh, các lõi không khớp với điều kiện chỉ dừng lại. Các dữ liệu tương tự sau đó được gửi thông qua một lần nữa, nhưng với các hướng dẫn so sánh đảo ngược. – David

+1

Trong trường hợp của bạn, bạn không thể so sánh với điểm ảnh sáng trước * ngay lập tức *, bởi vì bất kỳ (cho phép nói) 128 lõi có thể đã tìm thấy một điểm ảnh sáng hơn. Thay vào đó, hãy thử có mỗi lõi tập trung vào chỉ là dòng riêng của nó - tìm điểm ảnh sáng nhất trong dòng (xử lý 128 dòng cùng một lúc). Một khi các dòng trong hình ảnh có hiệu quả được tóm tắt như chỉ là điểm ảnh sáng nhất trong dòng đó, bạn có thể tìm thấy các sáng tổng thể trong một cách nối tiếp. – David

1

Đặt máy ảnh ra ngoài tiêu cự và bitblt đối với mẫu trung tính. Bạn có thể nhanh chóng quét các hàng cho các giá trị không 0. Ngoài ra nếu bạn đang ở 8 bit và nhận 4 byte tại một thời điểm bạn có thể xử lý hình ảnh nhanh hơn. Như đã chỉ ra khác, bạn có thể giảm tốc độ khung hình. Nếu bạn có độ trung thực kém hơn hình ảnh kết quả thì không có nhiều điểm trong tốc độ quét cao.

(The nhẹ ra khỏi máy ảnh tập trung sẽ giúp có được chỉ là điểm sáng nhất và giảm dương tính giả nếu bạn có một bề mặt bận rộn ... tất nhiên giả sử bạn không được chụp một bề mặt nhẵn/căn hộ)

2

tối ưu hóa khác để xem xét: nếu bạn đang vẽ, thì vị trí hiện tại của con trỏ có thể đóng vị trí cuối cùng của con trỏ. Nhớ vị trí được ghi cuối cùng của con trỏ giữa các khung và chỉ quét vùng gần vị trí đó ... nói vùng 1'x1 '. Chỉ khi con trỏ không được tìm thấy trong khu vực đó, bạn nên quét toàn bộ bề mặt.

Rõ ràng, sẽ có sự cân bằng giữa tốc độ chương trình của bạn có thể quét và tốc độ di chuyển chuột của bạn trước khi máy ảnh "mất" con trỏ và phải chuyển sang chế độ chậm, đầy đủ quét. Một thử nghiệm nhỏ có thể sẽ tiết lộ giá trị tối ưu.

Dự án tuyệt vời, nhân tiện.

+0

Tại sao chỉ 1x1. Tại sao không tăng kích thước 1^2. Vì vậy, nếu không tìm thấy trong một 1x1 nó sau đó sẽ kiểm tra 2x2, 4x4 vv Một chút chăm sóc và bạn có thể sải chân trên khu vực bạn đã kiểm tra. –

+0

Tôi cũng nghĩ về điều đó. Nhưng anh ta có thể có nhiều laser nên anh ta sẽ phải nhìn vào mọi điểm ảnh. Một tia laser có thể bật hoặc quay lại khu vực mà không cần thông báo. – Nosredna

1

Bắt đầu với bộ đệm đầu ra màu đen. Hãy quên đi subpixel cho bây giờ. Mỗi khung hình, mỗi pixel, thực hiện điều này:

outbuff = max (outbuff, inbuff);

Làm bộ lọc subpixel thành bộ đệm "sạch" thứ ba khi bạn đã hoàn tất với hình ảnh. Hoặc làm một đoạn hoặc một dòng của màn hình tại một thời điểm trong thời gian thực. Ưu điểm: thời gian thực "thô" xem của bản vẽ, làm sạch như bạn đi.

Khi bạn chuyển đổi từ bộ đệm đầu ra thô thành bộ đệm thứ ba "sạch", bạn có thể xóa phần thô thành màu đen. Điều này cho phép bạn tiếp tục vẽ mãi mãi mà không bị chậm lại.

Bằng cách vẽ "sạch" trên đầu trang "thô", có thể có màu hơi khác, bạn sẽ có điều tốt nhất của cả hai thế giới.

Điều này tương tự như những chương trình vẽ - nếu bạn vẽ rất nhanh, bạn sẽ thấy phiên bản thô, sau đó chương trình vẽ "dọn dẹp" hình ảnh khi có thời gian.


Một số ý kiến ​​về các thuật toán:

Tôi đã nhìn thấy rất nhiều lận trong lĩnh vực này. Tôi đã chơi Sonic trên một bộ giả lập Sega Genesis làm nổi loạn. và nó có một số thuật toán khá hoang dã hoạt động rất tốt và rất nhanh.

Bạn thực sự có một số lợi thế bạn có thể đạt được bởi vì bạn có thể biết độ sáng và bán kính trên chấm.

Bạn có thể chỉ cần nhìn vào từng điểm ảnh và 8 hàng xóm của nó và để cho 9 pixel đó "bình chọn" theo độ sáng của chúng cho vị trí của pixel phụ.


suy nghĩ khác

Bàn tay của bạn không phải là chính xác khi bạn điều khiển một con trỏ laser. Hãy thử lấy tất cả các dấu chấm sau mỗi 10 khung hình, xác định các dầm nào (dựa trên chuyển động trước đó, và tính toán các dấu chấm mới, các laser đã tắt và các dấu chấm đã nhập hoặc rời khỏi trường trực quan), sau đó chỉ vẽ đường cong độ phân giải. Đừng lo lắng về pixel phụ trong đầu vào - chỉ cần vẽ đường cong vào đầu ra có độ phân giải cao.

Sử dụng đường cong Catmull-Rom, chạy qua tất cả các điểm kiểm soát.

+0

Tôi thích ý tưởng này, có ý nghĩa hoàn hảo. Vì vậy, có thể đại diện cho các pixel "sạch" như các cấu trúc chứa các giá trị 5x5 pixel và đi qua chúng trong một hàng đợi trên một chuỗi riêng biệt. Tuy nhiên, việc đốt cháy hàng đợi này sẽ là một CPU lớn thực hiện. Có lẽ tôi có thể lưu trữ mỗi một trong những cấu trúc trong một đỉnh và làm đường cong spline trên card màn hình? Tôi vẫn đang tìm kiếm một cách chiếu sáng nhanh để tính toán các xiên 2D 5x5. Cảm ơn bạn đã đề xuất cấp cao này! – bufferz

+0

Nó thực sự không quan trọng nó chậm như thế nào. Bạn có thể tối ưu hóa sau. Bạn chỉ cần xem bộ đếm thời gian và xem bạn có thể làm bao nhiêu màn hình cho mỗi khung hình. – Nosredna

Các vấn đề liên quan