Как получить размеры и формат изображения EVF LiveView?

Во-первых, позвольте мне опубликовать ссылки на некоторые похожие вопросы SO, которые я нашел через Google. Первая ссылка, кажется, имеет правильный ответ, но она не решает мою проблему напрямую. Вторая ссылка напрямую касается моей проблемы, но ответ gdh, похоже, мне не помогает.

Canon LiveView: преобразование изображения в OpenCV Mat

Canon EDSDK Как я могу получить ширина и высота изображения в режиме реального времени?

Что я пытаюсь сделать, загружая изображения с моего Canon Rebel в режиме Live View с помощью Canon EDSDK. Я могу открыть поток и непрерывно загружать поток данных, но я не понимаю, как преобразовать эти данные в пригодное для использования изображение. В конечном счете, моя цель - загрузить изображения в реальном времени непосредственно в текстуру OpenGL через glTexSubImage2D, но я не понимаю, как получить битовую глубину изображения, формат цвета и размеры.

Позвольте мне опубликовать пример кода; пожалуйста, имейте в виду, что это урезанный пример моего рабочего кода - я опускаю некоторые детали, такие как запуск потока, получение ссылки на камеру или освобождение каких-либо ссылок, и на практике загрузка и вызовы OpenGL происходят в разных потоках.

// All my variables
EdsStreamRef evfStream = nullptr;     // evf datastream
EdsImageRef evfImg = nullptr;         // image ref
EdsCameraRef camRef = nullptr;        // camera ref
void * pData = nullptr;               // Pointer to image data
EdsUInt64 uLength( 0 );               // Size in bytes of image data
GLuint uGLTexID( 0 );                 // Handle to OpenGL texture
EdsSize imgSize{0};                   // Width, height of image
GLuint uClrFmt = GL_RGB;              // Color format of image
GLuint uClrType = GL_UNSIGNED_BYTE;   // Color data type of image

//////////////////////////////////////////////////////////////////////
// Get image from camera

// Create memory stream, init size to 1 byte for now
EdsCreateMemoryStream( 1, &evfStream );

// Create an image ref from the streawm
EdsCreateEvfImageRef( evfStream, &evfImg );

// Download the image (which I believe resizes the stream)
EdsDownloadEvfImage( camRef, evfImg );

// Get data size and pointer
EdsGetLength( evfStream, &uLength );
EdsGetPointer( evfStream, &pData );

//////////////////////////////////////////////////////////////////////
// Get image info

// This doesn't seem to be correct, using these dimensions causes a crash
EdsGetPropertyData( m_WriteImg.imgRef, kEdsPropID_Evf_CoordinateSystem, 0, sizeof( EdsSize ), &imgSize );

// How do I get these two?
uClrFmt = GL_RGB;
uClrType = GL_UNSIGNED_BYTE;

//////////////////////////////////////////////////////////////////////
// Upload to GPU

// If this is the first time, create the texture
bool bFirstTime = true;
if ( bFirstTime )
{
    //Generate the device texture and bind it
    glGenTextures( 1, &uGLTexID );
    glBindTexture( GL_TEXTURE_2D, uGLTexID );

    //Upload host texture to device
    glTexImage2D( GL_TEXTURE_2D, 0, uClrFmt, imgSize.width, imgSize.height, 0, uClrFmt, uClrType, pData );

    // Unbind
    glBindTexture( GL_TEXTURE_2D, 0 );

    bFirstTime = false;
}
// Otherwise update the existing texture
else
{
    // Bind texture
    glBindTexture( GL_TEXTURE_2D, uGLTexID );

    // Upload image
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, imgSize.width, imgSize.height, uClrType, uClrFmt, pData );

    // Unbind
    glBindTexture( GL_TEXTURE_2D, 0 );
}

Отсутствующие части - это то, как получить фактическое изображение и его свойства. Образец EDSDK, а также вопрос, связанный с OpenCV, предоставляют пример того, как преобразовать эти данные в пригодное для использования изображение, но оба предполагают использование другой библиотеки для помещения данных в пригодное для использования изображение.

В примере EDSDK GDI+ используется для создания объекта CImage. В своем отладчике я вижу, что созданный CImage имеет разрядность 24 и размеры 1056x704 (или что-то в этом роде), но я понятия не имею, как эти данные извлекаются.

Больше всего меня смущает то, что переменная uLength, представляющая собой размер потока данных в байтах, не остается постоянной (каждый раз она меняется на относительно небольшую величину). Как это возможно, если фактическое изображение размер кажется постоянным?

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

Спасибо,

Джон


person mynameisjohnj    schedule 10.09.2016    source источник


Ответы (1)


насколько я знаю, функции для получения размера живого изображения нет, да и необходимости в этом нет. Кадр просмотра в реальном времени, который вы загружаете, представляет собой стандартный jpg, поэтому вы можете узнать размер, прочитав его заголовок. Я не знаю, как OpenCV или OpenGL работают с изображениями в формате jpg, но я уверен, что есть какая-то функция, если они поддерживают чтение этого формата. В противном случае вы можете использовать одну из многих библиотек jpg. Сжатие jpg также объясняет, почему размер изображения варьируется между кадрами.

Что вы на самом деле получаете, вызывая EdsGetPropertyData с kEdsPropID_Evf_CoordinateSystem, так это размер системы координат просмотра в реальном времени. Это определенно не размер живого просмотра. Я думаю, что это ближе к размеру фотографии, но я не совсем уверен в этом.

person Johannes Bildstein    schedule 10.09.2016
comment
Спасибо. Итак, ответ заключается в том, что это изображение в формате jpg, и для того, чтобы получить необработанные байты, я должен сначала распаковать его. У OpenCV есть возможности для этого, но OpenGL сам по себе этого не делает. Однако я использую SDL2 для создания своего контекста OpenGL, поэтому, возможно, в образе SDL есть то, что мне нужно. - person mynameisjohnj; 11.09.2016
comment
@ user1973454, да, верно. Если у вас есть проблемы с чтением jpg, вы всегда можете использовать что-то вроде libjpeg. Это должно быть очень быстро, и я не удивлюсь, если OpenCV использует его и под капотом. - person Johannes Bildstein; 11.09.2016