WinRT C++ (Win10), opencv HSV color space, image display, artifacts

ⅰ亾dé卋堺 提交于 2019-12-13 06:47:24

问题


My goal is to make an object tracking.

I have a UWP c# app and linked c++ windows runtime component. There I can obtain acces to opencv.

  • In c#, MediaCapture return SoftwareBitmap.
  • Then I pass SoftwareBitmap to c++ and convert it to opencv's Mat.
  • Then cvtColor(cvFrame, cvFrame, COLOR_BGR2HSV);
  • And then convert back to SoftwareBitmap, with BitmapPixelFormat::Bgra8 (only Bgra8 is accepted by Software Bitmap) and BitmapAlphaMode::Ignore

And there is what I've got screen

If I skip a cvtColor part and just convert to cv::Mat and back to SoftwareBitmap, I've got a nice image in result ...

I understand that there is a problem with image's channels ... but I've lost where to dig. I assume that cv::Mat after cvtColor is right ... but I want to see intermediate steps of a picture creation. (HSV, threshold, and then result)

Any advice would be appreciated.

PS I've tried imwrite but no file is created.

Update Conversion from/to

Mat Convert(SoftwareBitmap^ from)
{
    BitmapBuffer^ bmpBuffer = from->LockBuffer(BitmapBufferAccessMode::ReadWrite);

    unsigned char* pPixels = GetPointerToPixelData(bmpBuffer->CreateReference());

    Mat mat(from->PixelHeight, from->PixelWidth, CV_8UC4);
    memcpy(mat.data, pPixels, 4 * from->PixelHeight * from->PixelWidth);

    return mat;
}

SoftwareBitmap^ Convert(Mat from)
{
    SoftwareBitmap^ sBitmap = ref new SoftwareBitmap(BitmapPixelFormat::Bgra8, from.cols, from.rows, BitmapAlphaMode::Ignore);
    BitmapBuffer^ bmpBuffer = sBitmap->LockBuffer(BitmapBufferAccessMode::ReadWrite);
    auto reference = bmpBuffer->CreateReference();

    unsigned char* dstPixels = GetPointerToPixelData(reference);
    memcpy(dstPixels, from.data, from.step.buf[1] * from.cols*from.rows);

    return sBitmap;
}

unsigned char* GetPointerToPixelData(IBuffer^ buffer)
{
    ComPtr<IBufferByteAccess> bufferByteAccess;
    ComPtr<IInspectable> insp((IInspectable*)buffer);
    ThrowIfFailed(insp.As(&bufferByteAccess));

    unsigned char* pixels = nullptr;
    ThrowIfFailed(bufferByteAccess->Buffer(&pixels));

    return pixels;
}

unsigned char* GetPointerToPixelData(IMemoryBufferReference^ reference)
{
    ComPtr<IMemoryBufferByteAccess> bufferByteAccess;

    ThrowIfFailed(reinterpret_cast<IInspectable*>(reference)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess)));

    unsigned char* pixels = nullptr;
    unsigned int capacity = 0;
    ThrowIfFailed(bufferByteAccess->GetBuffer(&pixels, &capacity));

    return pixels;
}

回答1:


Since you didn't post the code that does the actual conversion from/to SoftwareBitmap/cv::Mat.

My best guess is that 3-channel image data is displayed as if there where 4 channels.




回答2:


Ok, I figured out the solution.

//convert from SoftwareBitmap to Mat
Mat cvFrame = this->Convert(frame);

//change color space
cvtColor(cvFrame, cvFrame, COLOR_BGR2HSV);

// split chanels
vector<Mat> hsvChannels(3);
split(cvFrame, hsvChannels);

//create empty chanel
Mat empty;
empty = Mat::zeros(cvFrame.rows, cvFrame.cols, CV_8UC1);

// create hsv with empty alpha
vector<Mat> channels;
channels.push_back(hsvChannels[0]); //h
channels.push_back(hsvChannels[1]); //s
channels.push_back(hsvChannels[2]); //v
channels.push_back(empty); //a

//put back to Mat
merge(channels, cvFrame);

// convert back to SoftwareBitmap 
return this->Convert(cvFrame);


来源:https://stackoverflow.com/questions/34198259/winrt-c-win10-opencv-hsv-color-space-image-display-artifacts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!