问题
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