2015-06-04 52 views
5

Tôi đang sử dụng máy tính bảng google tango để thu thập dữ liệu đám mây điểm và hình ảnh camera RGB. Tôi muốn tạo bản scan 3D của căn phòng. Vì vậy, tôi cần ánh xạ các điểm ảnh của điểm ảnh 2D đến điểm đám mây. Tôi sẽ làm điều này với rất nhiều đám mây điểm và hình ảnh tương ứng. Tôi cần phải viết một kịch bản mã có hai đầu vào 1. đám mây điểm và 2. hình ảnh được lấy từ cùng một điểm theo cùng một hướng và tập lệnh sẽ xuất ra điểm màu đám mây. Làm thế nào tôi nên tiếp cận này & nền tảng nào sẽ rất đơn giản để sử dụng?cách tô điểm đám mây điểm từ điểm ảnh?

Trả lời

5

Đây là toán học để ánh xạ một điểm 3D v vào không gian điểm ảnh 2D trong hình ảnh camera (giả định rằng v đã kết hợp các vị trí camera bên ngoài và định hướng, xem chú thích ở dưới *):

// Project to tangent space. 
vec2 imageCoords = v.xy/v.z; 

// Apply radial distortion. 
float r2 = dot(imageCoords, imageCoords); 
float r4 = r2*r2; 
float r6 = r2*r4; 
imageCoords *= 1.0 + k1*r2 + k2*r4 + k3*r6; 

// Map to pixel space. 
vec3 pixelCoords = cameraTransform*vec3(imageCoords, 1); 

đâu cameraTransform là ma trận 3x3:

[ fx 0 cx ] 
[ 0 fy cy ] 
[ 0 0 1 ] 

với fx, fy, cx, cy, k1, k2, k3 từ TangoCameraIntrinsics.

pixelCoords được khai báo vec3 nhưng thực ra là 2D ở tọa độ đồng nhất. Tọa độ thứ ba luôn là 1 và vì vậy có thể bỏ qua cho các mục đích thực tế. Lưu ý rằng nếu bạn muốn tọa độ kết cấu thay vì tọa độ pixel, đó chỉ là một biến đổi tuyến tính có thể được xử lý trước lên cameraTransform trước thời hạn (như là bất kỳ địa chỉ quét từ đầu đến cuối nào so với từ trên xuống dưới). .

Đối với "nền tảng" (mà tôi được hiểu là "ngôn ngữ") đơn giản nhất, native API có vẻ là cách đơn giản nhất để có được các điểm ảnh trên máy ảnh, mặc dù dường như mọi người cũng đã thành công với UnityJava.


* Điểm được phân phối bởi TangoXYZij đã kết hợp máy ảnh chiều sâu bên ngoài biến đổi. Về mặt kỹ thuật, vì máy tính bảng nhà phát triển hiện tại có cùng phần cứng giữa độ sâu và thu thập hình ảnh màu, bạn sẽ không thể có được hình ảnh màu khớp chính xác trừ khi cả thiết bị và cảnh của bạn đều dừng. May mắn thay trong thực tế, hầu hết các ứng dụng có thể giả định rằng không phải máy ảnh đặt ra cũng như cảnh thay đổi đủ trong một khung thời gian để ảnh hưởng đáng kể đến việc tra cứu màu sắc.

2

Câu trả lời này không phải là bản gốc, nó chỉ đơn giản là tiện lợi cho người dùng Unity muốn có câu trả lời đúng, như được cung cấp bởi @rhashimoto, đã làm việc cho họ. Đóng góp của tôi (hy vọng) là cung cấp mã mà làm giảm bình thường 16 nhân và 12 cho biết thêm (cho Unity chỉ 4x4 ma trận) đến 2 nhân và 2 cho biết thêm bằng cách bỏ tất cả các kết quả bằng không. Tôi chạy dưới một triệu điểm thông qua thử nghiệm, kiểm tra mỗi lần tính toán của tôi đồng ý với các phép tính ma trận cơ bản - được định nghĩa là sự khác biệt tuyệt đối giữa hai kết quả nhỏ hơn epsilon máy - Tôi cảm thấy thoải mái với điều này biết rằng @rhashimoto có thể hiển thị và chọc một lỗ khổng lồ trong đó :-)

Nếu bạn muốn chuyển đổi qua lại, hãy nhớ đây là C#, vì vậy định nghĩa USEMATRIXMATH phải xuất hiện ở đầu tệp.

Do chỉ có một thiết bị Tango ngay bây giờ, và tôi giả intrinsics là liên tục trên tất cả các thiết bị, tôi chỉ đổ chúng vào như hằng số, chẳng hạn rằng

fx = 1042.73999023438 
fy = 1042.96997070313 
cx = 637.273986816406 
cy = 352.928985595703 
k1 = 0.228532999753952 
k2 = -0.663019001483917 
k3 = 0.642908990383148 

Có họ có thể được đổ như là hằng số, điều này sẽ làm cho mọi thứ dễ đọc hơn, và C# có lẽ đủ thông minh để tối ưu hóa nó - tuy nhiên, tôi đã dành quá nhiều thời gian trong công cụ của Agner Fogg, và sẽ luôn bị hoang tưởng.

Mã nhận xét ở dưới cùng là để kiểm tra sự khác biệt, nếu bạn muốn. Bạn sẽ phải bỏ ghi chú một số nội dung khác và nhận xét lợi nhuận nếu bạn muốn kiểm tra kết quả.

tôi nhờ một lần nữa để @rhashimoto, đây là xa tốt hơn nhiều so với những gì tôi đã

Tôi đã ở đúng logic của mình, hãy nhớ đây là những tọa độ pixel, không UV phối - ông là đúng mà bạn có thể premultiply các chuyển đổi để có được giá trị UV bình thường, nhưng kể từ khi ông dạy cho tôi về vấn đề này một lần rồi, tôi sẽ gắn bó với chính xác toán học ông đã trình bày trước khi tôi fiddle với quá nhiều :-)

static public Vector2 PictureUV(Vector3 tangoDepthPoint) 
    { 
     Vector2 imageCoords = new Vector2(tangoDepthPoint.x/tangoDepthPoint.z, tangoDepthPoint.y/tangoDepthPoint.z); 
     float r2 = Vector2.Dot(imageCoords, imageCoords); 
     float r4 = r2*r2; 
     float r6 = r2*r4; 
     imageCoords *= 1.0f + 0.228532999753952f*r2 + -0.663019001483917f*r4 + 0.642908990383148f*r6; 
     Vector3 ic3 = new Vector3(imageCoords.x,imageCoords.y,1); 

#if USEMATRIXMATH 
     Matrix4x4 cameraTransform = new Matrix4x4(); 
     cameraTransform.SetRow(0,new Vector4(1042.73999023438f,0,637.273986816406f,0)); 
     cameraTransform.SetRow(1, new Vector4(0, 1042.96997070313f, 352.928985595703f, 0)); 
     cameraTransform.SetRow(2, new Vector4(0, 0, 1, 0)); 
     cameraTransform.SetRow(3, new Vector4(0, 0, 0, 1)); 
     Vector3 pixelCoords = cameraTransform * ic3; 
     return new Vector2(pixelCoords.x, pixelCoords.y); 
#else 
     //float v1 = 1042.73999023438f * imageCoords.x + 637.273986816406f; 
     //float v2 = 1042.96997070313f * imageCoords.y + 352.928985595703f; 
     //float v3 = 1; 
     return new Vector2(1042.73999023438f * imageCoords.x + 637.273986816406f,1042.96997070313f * imageCoords.y + 352.928985595703); 
#endif 

     //float dx = Math.Abs(v1 - pixelCoords.x); 
     //float dy = Math.Abs(v2 - pixelCoords.y); 
     //float dz = Math.Abs(v3 - pixelCoords.z); 
     //if (dx > float.Epsilon || dy > float.Epsilon || dz > float.Epsilon) 
     // UnityEngine.Debug.Log("Well, that didn't work"); 
     //return new Vector2(v1, v2); 
    } 

là một lưu ý cuối cùng, làm chú ý mã mà anh ấy cung cấp là GLSL - nếu bạn chỉ sử dụng nó cho những bức ảnh đẹp, hãy sử dụng nó - điều này là dành cho những người thực sự cần thực hiện thêm chế biến itional.

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