2015-12-07 3 views
1

Я пытаюсь создать облако точек, где каждая точка имеет цвет. Я могу получить только облако точек, или я могу заставить камеру сделать снимок, но мне нужно, чтобы они были максимально возможными. Если бы я мог искать RGB-изображение с отметкой времени или вызывать функцию для получения текущего кадра при вызове onXYZijAvailable(), я бы это сделал. Я мог бы просто перейти по точкам, узнать, где он будет пересекаться с плоскостью изображения и получить цвет этого пикселя.Извлечь pointclouds с цветом с использованием Project Tango; то есть получение текущего кадра камеры

Как сейчас, я не нашел способа получить информацию о пикселях изображения или получить цветные точки. Я видел приложения AR, где камера подключена к CameraView, а затем вещи отображаются сверху, но поток камеры никогда не затрагивается приложением.

Согласно сообщению this, должно быть возможно получить нужные данные и синхронизировать облако точек и плоскость изображения простым преобразованием. This сообщение также говорит что-то подобное. Однако я не знаю, как получить данные RGB. Я не могу найти какие-либо проекты с открытым исходным кодом или учебные пособия.

Ближайшим Я получил это выяснить, когда кадр готов с помощью этого:

 public void onFrameAvailable(final int cameraId) { 
      if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) { 
       //Get the new rgb frame somehow. 
      } 
    } 

Я работаю с API Java, и я очень хотел бы, чтобы не углубляться в JNI и если NDK во всех возможных. Как я могу получить фрейм, который наиболее точно соответствует временной метке моего текущего облака точек?

Благодарим за помощь.

Update:

Я реализовал версию процессора этого и даже после оптимизации его немного мне удалось получить .5 FPS на маленьком облаке точек. Это также связано с тем, что цвета должны быть преобразованы из собственного цветного пространства NV21 в андроид в цветовое пространство RGBA на GPU. Я мог бы оптимизировать его дальше, но я не собираюсь получать эффект в реальном времени с этим. Процессор на устройстве Android просто не может работать достаточно хорошо. Если вы хотите сделать это более чем на несколько тысяч пунктов, пойдите для дополнительной проблемы с использованием GPU или сделайте это в сообщении.

ответ

3

Tango обычно передает цветные пиксельные данные непосредственно в текстуру OpenGLES. В Java вы создаете текстуру назначения и регистрируете ее с помощью Tango.connectTextureId(), затем в обратном вызове onFrameAvailable() вы обновляете текстуру с помощью Tango.updateTexture(). После того, как у вас есть цветное изображение в текстуре, вы можете получить к нему доступ, используя вызовы рисования OpenGLES и шейдеры.

Если ваша цель - окрасить облако точек танго, наиболее эффективный способ сделать это - в графическом процессоре. То есть вместо того, чтобы вытаскивать цветное изображение из графического процессора и получать доступ к нему в Java, вы вместо этого передаете данные точки в графический процессор и используете шейдеры OpenGLES для преобразования 3D-точек в 2D-координаты текстуры и поиска цветов из текстуры. Это довольно сложно получить, если вы делаете это в первый раз, но может потребоваться для приемлемой производительности.

Если вы действительно хотите прямой доступ к данным пикселя без использования C API, вам нужно, чтобы сделать текстуру в буфер, а затем прочитать цветовые данные из буфера. Это довольно сложно, если вы не используете OpenGL и не пишете шейдеры, но есть приложение для Android Studio, которое демонстрирует это here и описано далее в this answer. Этот проект демонстрирует как рисовать текстуру камеры на экране, так и как рисовать в буфер вне экрана и считывать пиксели RGBA.

Если вы действительно хотите прямой доступ к данным пикселя, но решили, что NDK может быть менее болезненным, чем OpenGLES, С API имеет TangoService_connectOnFrameAvailable(), который дает вам пиксельные данные непосредственно, то есть без прохождения через OpenGLES. Обратите внимание, однако, что формат данных пикселей - NV21, не RGB или RGBA.

+0

У меня нет проблем с OpenGL, к счастью. Это андроид и API танго, с которыми я борюсь. Я закончил с использованием NDK для извлечения данных. Я знаю, что могу напрямую связать цветное изображение с текстурой, но мне нужен доступ к данным, чтобы изменить его и передать данные на сервер для анализа. Я написал функцию TangoService_connectOnFrameAvailable() перед тем, как отправиться домой сегодня, поэтому завтра я буду работать над извлечением данных. Я очень рад видеть производительность пересечения границы между c и java и насколько дорого нужно извлечь изображение! Спасибо за ваш ответ. –

+0

Даже если вам нужны цветные точки вне графического процессора, весьма вероятно, что наиболее эффективным способом их цветопередачи является использование графического процессора. То есть, будет менее дорого обтекать данные облачных облаков, сделать магию OpenGL в renderbuffer и потопить данные из renderbuffer, чем делать эти поисковые запросы (с возможностью интерполяции, возможно) и преобразования цветового пространства на CPU , – rhashimoto

+0

Я хочу увидеть peeformance в первую очередь, поскольку программирование GPGPU на андроиде может быть более опасным. Если это слишком медленно, я попытаюсь это сделать. У вас есть данные по этому поводу? –

1

Я делаю это сейчас, захватывая глубину с помощью onXYZijAvailable() и изображений с помощью onFrameAvailable(). Я использую собственный код, но то же самое должно работать на Java. Для каждого onFrameAvailable() я получаю данные изображения и помещаю их в предварительно выделенный кольцевой буфер. У меня 10 слотов и счетчик/указатель. Каждое новое изображение увеличивает счетчик, который возвращается с 9 на 0. Счетчик представляет собой индекс в массив изображений. Я сохраняю метку времени изображения в подобном кольцевом буфере. Когда я получаю изображение глубины, onXYZijAvailable(), я захватываю данные и метку времени. Затем я возвращаюсь к изображениям, начиная с самого последнего и перемещаясь назад, пока не нахожу тот, у которого самая близкая метка времени к данным глубины. Как вы уже упоминали, вы знаете, что данные изображения не будут из того же кадра, что и данные глубины, потому что они используют одну и ту же камеру. Но, используя эти два вызова (в JNI), я получаю в пределах +/- 33 мс, т. Е. Предыдущий или следующий кадр, на постоянной основе.

Я не проверял, насколько близко было бы наивно использовать недавно обновленный кадр изображения rgb, но это должно быть довольно близко.

Просто убедитесь, что onXYZijAvailable() используется для синхронизации времени, потому что глубина обновляется медленнее, чем rgb.

Я обнаружил, что запись отдельных изображений в файловую систему с использованием OpenCV :: imwrite() не соответствует текущему времени работы камеры. Я не пытался передавать потоки в файл с помощью видеокодека. Это должно быть намного быстрее. В зависимости от того, что вы планируете делать с данными в конце, вам нужно быть осторожным, как вы храните свои результаты.

+0

API Java и C не ведут себя одинаково. Несмотря на то, что обратный вызов C' onFrameAvailable() 'передает данные пикселов, обратный вызов Java этого не делает. Получение пиксельных данных в чистой Java требует прохождения OpenGL. – rhashimoto