2016-09-07 27 views
6

Mục tiêu của tôi là chạy mô hình TensorFlow trong thời gian thực để điều khiển xe từ mô hình đã học. Hệ thống xe của chúng tôi sử dụng ROS (Hệ điều hành Robot) được gắn chặt với OpenCV. Vì vậy, tôi nhận được một OpenCV Mat chứa hình ảnh quan tâm từ ROS.Nhập OpenCV Mat vào C++ Tensorflow mà không cần sao chép

cv::Mat cameraImg; 

Tôi muốn tạo Tensorflow Tensor trực tiếp từ dữ liệu trong ma trận OpenCV này để tránh chi phí sao chép ma trận từng dòng một. Sử dụng câu trả lời cho This Question tôi đã được quản lý để có được những đường chuyền về phía trước của mạng lưới làm việc với đoạn mã sau:

cameraImg.convertTo(cameraImg, CV_32FC3); 

Tensor inputImg(DT_FLOAT, TensorShape({1,inputheight,inputwidth,3})); 
auto inputImageMapped = inputImg.tensor<float, 4>(); 
auto start = std::chrono::system_clock::now(); 
//Copy all the data over 
for (int y = 0; y < inputheight; ++y) { 
    const float* source_row = ((float*)cameraImg.data) + (y * inputwidth * 3); 
    for (int x = 0; x < inputwidth; ++x) { 
     const float* source_pixel = source_row + (x * 3); 
     inputImageMapped(0, y, x, 0) = source_pixel[2]; 
     inputImageMapped(0, y, x, 1) = source_pixel[1]; 
     inputImageMapped(0, y, x, 2) = source_pixel[0]; 
    } 
} 
auto end = std::chrono::system_clock::now(); 

Tuy nhiên, sử dụng phương pháp này, các bản sao cho tensor mất khoảng 80ms và 130ms, trong khi toàn bộ đường chuyền về phía trước (đối với mạng chuyển tiếp 10 lớp) chỉ mất 25ms.

Nhìn vào the tensorflow documentation, có vẻ như có một hàm tạo Tensor có trình phân bổ. Tuy nhiên, tôi không thể tìm thấy bất kỳ tài liệu Tensorflow hoặc Eigen nào liên quan đến chức năng này hoặc Eigen Map class vì nó liên quan đến Tensors.

Có ai có thông tin chi tiết về cách mã này có thể được tăng tốc hay không, lý tưởng nhất là sử dụng lại bộ nhớ OpenCV của tôi?

EDIT: Tôi đã triển khai thành công những gì @mrry đề xuất và có thể sử dụng lại bộ nhớ do OpenCV cấp. Tôi đã mở github issue 8033 yêu cầu điều này được thêm vào cây nguồn tensorflow. Phương pháp của tôi không đẹp, nhưng nó hoạt động.

Vẫn còn rất khó để biên dịch một thư viện bên ngoài và liên kết nó với thư viện libtensorflow.so. Có khả năng tensorflow cmake library sẽ giúp ích cho điều này, tôi chưa thử.

Trả lời

6

API TensorFlow C (ngược với API C++) xuất hàm TF_NewTensor(), cho phép bạn tạo một tensor từ một con trỏ và chiều dài, và bạn có thể chuyển đối tượng kết quả đến hàm TF_Run().

Hiện tại, đây là API công cộng duy nhất để tạo ra một tensor TensorFlow từ bộ đệm được cấp phát trước. Không có cách nào được hỗ trợ để đúc TF_Tensor* thành tensorflow::Tensor nhưng nếu bạn xem xét triển khai, có một API riêng với quyền truy cập friend có thể thực hiện việc này. Nếu bạn thử nghiệm với điều này và có thể hiển thị một tốc độ đáng tin cậy, chúng tôi sẽ xem xét một feature request để thêm điều này vào API công khai.

+0

Awesome, cảm ơn cho phản ứng nhanh chóng! Tôi sẽ cố gắng sử dụng C api để có được một tensor vào mã của tôi. Tôi sử dụng api C++ hiện tại để tải đồ thị của tôi từ đĩa, vì vậy tôi đoán tôi sẽ phải cố gắng sử dụng API bạn bè riêng. Tôi sẽ cho bạn biết ngay sau khi tôi có thể nhận được kết quả. – Paul

+0

Tôi đang cố gắng để có được điều này để làm việc với thư viện bên ngoài của tôi nhưng không có may mắn biên dịch nó. Tôi có thể làm cho trình biên dịch hài lòng bằng cách khai báo lớp TensorCApi và lớp TF_Tensor trong nguồn của tôi.Tuy nhiên, khi tôi chạy nó, tôi nhận được một lỗi: '/ opt/ros/indigo/lib/nodelet/nodelet: lỗi tra cứu ký hiệu: /home/paul/catkin_ws/devel/lib//libDeepModel.so: biểu tượng không xác định: TF_NewTensor '. Khi tôi cố định nghĩa lớp trong nguồn tensorflow (trong 'c_api.h'), có vẻ như nó không được biên dịch. Tôi đang sử dụng mục tiêu xây dựng '// tensorflow: libtensorflow.so', mục tiêu xây dựng này không bao gồm api C? – Paul

+1

Bạn đã bao giờ làm việc này chưa? Nếu vậy, bạn có bất kỳ đoạn mã nào mà bạn có thể chia sẻ không? Tôi cũng đang tìm cách để giao tiếp opencv từ ROS và cần một cái gì đó như thế này. Tôi đã rất ngạc nhiên khi tôi bắt đầu nhìn vào điều này rằng cách duy nhất để có được một opencv Mat thành một Tensor là một vòng lặp sao chép khủng khiếp chậm. – dcofer

4

Tôi biết rằng đó là chủ đề cũ nhưng có một giải pháp sao chép không cho vấn đề của bạn bằng cách sử dụng API C++ hiện tại: Tôi đã cập nhật vấn đề github của bạn với giải pháp của tôi. tensorflow/issues/8033

Đối với hồ sơ sao chép giải pháp của tôi ở đây:

// allocate a Tensor 
Tensor inputImg(DT_FLOAT, TensorShape({1,inputHeight,inputWidth,3})); 

// get pointer to memory for that Tensor 
float *p = inputImg.flat<float>().data(); 
// create a "fake" cv::Mat from it 
cv::Mat cameraImg(inputHeight, inputWidth, CV_32FC3, p); 

// use it here as a destination 
cv::Mat imagePixels = ...; // get data from your video pipeline 
imagePixels.convertTo(cameraImg, CV_32FC3); 

Hope this helps

+1

Bất kỳ cách nào để thực hiện điều này cho một tensor có hàng loạt hình ảnh? Ví dụ: 'Tensor inputImg (DT_FLOAT, TensorShape ({4, inputHeight, inputWidth, 3}));' Vì tensors không thể ghi được, tôi tưởng tượng bạn sẽ tạo tensors cho mỗi ảnh, tải 'cv :: Mat 'vào nó, và kết hợp chúng bằng cách nào đó để forrn' inputImg'. Nếu vậy, có cách nào để kết hợp tensors? – Jim

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