2015-08-05 2 views
0

Для обработки моих предварительных кадров моей камеры в OpenCV мне нужен доступ к необработанным пиксельным данным/байтам. Итак, есть новый SoftwareBitmap, который должен точно обеспечить это.WinRT C++ (Win10) Доступ к байтам из SoftwareBitmap/BitmapBuffer

Существует example для C#, но в Visual C++ я не могу получить IMemoryBufferByteAccess (см. Примечания) Интерфейс работает.

код с исключениями:

// Capture the preview frame 
return create_task(_mediaCapture->GetPreviewFrameAsync(videoFrame)) 
    .then([this](VideoFrame^ currentFrame) 
{ 
    // Collect the resulting frame 
    auto previewFrame = currentFrame->SoftwareBitmap; 

    auto buffer = previewFrame->LockBuffer(Windows::Graphics::Imaging::BitmapBufferAccessMode::ReadWrite); 
    auto reference = buffer->CreateReference(); 

    // Get a pointer to the pixel buffer 
    byte* pData = nullptr; 
    UINT capacity = 0; 

    // Obtain ByteAccess 
    ComPtr<IUnknown> inspectable = reinterpret_cast<IUnknown*>(buffer); 
    // Query the IBufferByteAccess interface. 
    Microsoft::WRL::ComPtr<IMemoryBufferByteAccess> bufferByteAccess; 
    ThrowIfFailed(inspectable.As(&bufferByteAccess));  // ERROR ---> Throws HRESULT = E_NOINTERFACE 

    // Retrieve the buffer data. 
    ThrowIfFailed(bufferByteAccess->GetBuffer(_Out_ &pData, _Out_ &capacity));  // ERROR ---> Throws HRESULT = E_NOINTERFACE, because bufferByteAccess is null 

Я тоже попытался это:

HRESULT hr = ((IMemoryBufferByteAccess*)reference)->GetBuffer(&pData, &capacity); 

HRESULT это нормально, но я не могу получить доступ к PDATA -> нарушение прав доступа чтения памяти.

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

+0

Похоже, вы должны использовать 'Microsoft :: WRL :: ComPtr ' с 'reference', а не' buffer'. –

+0

Привет. Вам удалось отобразить изображение в цветовом пространстве HSV? У меня есть некоторые артефакты ... В C# (UWP) у меня есть пропуск SoftwareBitmap на C++, там конвертируется SoftwareBitmap в cv :: Mat, меняет цвет cpase на HSV, конвертирует Mat в SoftwareBitmap и переходит обратно в C# .. И set Image.Source ... И это то, что у меня есть .. https://onedrive.live.com/redir?resid=357572637B8B8769!150460&authkey=!ACmXOuwLkoOyxFY&v=3&ithint=photo%2cPNG – Gregsparrow

+0

Подробнее здесь http: //stackoverflow.com/questions/34198259/winrt-c-win10-opencv-hsv-color-space-image-display-artifacts – Gregsparrow

ответ

1

Вы должны использовать ссылку вместо буфера в reinterpret_cast.

#include "pch.h" 
#include <wrl\wrappers\corewrappers.h> 
#include <wrl\client.h> 

MIDL_INTERFACE("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d") 
IMemoryBufferByteAccess : IUnknown 
{ 
    virtual HRESULT STDMETHODCALLTYPE GetBuffer(
     BYTE **value, 
     UINT32 *capacity 
     ); 
}; 

     auto previewFrame = currentFrame->SoftwareBitmap; 

     auto buffer = previewFrame->LockBuffer(BitmapBufferAccessMode::ReadWrite); 

     auto reference = buffer->CreateReference(); 

     ComPtr<IMemoryBufferByteAccess> bufferByteAccess; 

     HRESULT result = reinterpret_cast<IInspectable*>(reference)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess)); 

     if (result == S_OK) 
     { 
      WriteLine("Get interface successfully"); 

      BYTE* data = nullptr; 

      UINT32 capacity = 0; 

      result = bufferByteAccess->GetBuffer(&data, &capacity); 

      if (result == S_OK) 
      { 
       WriteLine("get data access successfully, capacity: " + capacity); 
      } 
     } 
+0

Спасибо! 3 дня исследований, и это так просто .... ваш код даже решил проблему выделения памяти – Steffen

+0

Можете ли вы посмотреть на мой вопрос? http://stackoverflow.com/questions/34198259/winrt-c-win10-opencv-hsv-color-space-image-display-artifacts – Gregsparrow

0

Я в настоящее время доступ к сырой unsigned char* data из каждого кадра я получить на MediaFrameReader::FrameArrived случае без использования WRL и COM ...

Здесь как:

void MainPage::OnFrameArrived(MediaFrameReader ^reader, MediaFrameArrivedEventArgs ^args) 
{ 
    MediaFrameReference ^mfr = reader->TryAcquireLatestFrame(); 
    VideoMediaFrame ^vmf = mfr->VideoMediaFrame; 
    VideoFrame ^vf = vmf->GetVideoFrame(); 
    SoftwareBitmap ^sb = vf->SoftwareBitmap; 
    Buffer ^buff = ref new Buffer(sb->PixelHeight * sb->PixelWidth * 2); 
    sb->CopyToBuffer(buff); 
    DataReader ^dataReader = DataReader::FromBuffer(buffer); 
    Platform::Array<unsigned char, 1> ^arr = ref new Platform::Array<unsigned char, 1>(buffer->Length); 
    dataReader->ReadBytes(arr); 
    // here arr->Data is a pointer to the raw pixel data 
} 

ПРИМЕЧАНИЕ: Объект MediaCapture должен быть сконфигурирован с MediaCaptureMemoryPreference::Cpu, чтобы иметь действительный SoftwareBitmap

Надеюсь, что это поможет кому-то

Смежные вопросы