WinRT C++ (Win10)、opencv HSV 颜色 space、图像显示、伪像
WinRT C++ (Win10), opencv HSV color space, image display, artifacts
我的目标是进行对象跟踪。
我有一个 UWP c# 应用程序和链接的 c++ windows 运行时组件。在那里我可以获得对 opencv 的访问权限。
- 在 c# 中,MediaCapture return SoftwareBitmap。
- 然后我把SoftwareBitmap传给c++,转成opencv的Mat。
- 然后
cvtColor(cvFrame, cvFrame, COLOR_BGR2HSV);
- 然后转换回 SoftwareBitmap,使用 BitmapPixelFormat::Bgra8(只有 Bgra8 被 Software Bitmap 接受)和 BitmapAlphaMode::Ignore
这就是我所拥有的 screen
如果我跳过 cvtColor
部分并仅转换为 cv::Mat 并返回到 SoftwareBitmap,结果我得到了一个漂亮的图像...
我知道图像的通道有问题……但我不知道该去哪里挖掘。
我假设 cvtColor
之后的 cv::Mat 是正确的......但我想查看图片创建的中间步骤。 (HSV、阈值,然后是结果)
如有任何建议,我们将不胜感激。
PS
我试过 imwrite
但没有创建文件。
更新
转换 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;
}
因为您没有 post 执行实际转换的代码 from/to SoftwareBitmap/cv::Mat.
我最好的猜测是 3 通道图像数据显示时好像有 4 通道。
好的,我找到了解决方案。
//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);
我的目标是进行对象跟踪。
我有一个 UWP c# 应用程序和链接的 c++ windows 运行时组件。在那里我可以获得对 opencv 的访问权限。
- 在 c# 中,MediaCapture return SoftwareBitmap。
- 然后我把SoftwareBitmap传给c++,转成opencv的Mat。
- 然后
cvtColor(cvFrame, cvFrame, COLOR_BGR2HSV);
- 然后转换回 SoftwareBitmap,使用 BitmapPixelFormat::Bgra8(只有 Bgra8 被 Software Bitmap 接受)和 BitmapAlphaMode::Ignore
这就是我所拥有的 screen
如果我跳过 cvtColor
部分并仅转换为 cv::Mat 并返回到 SoftwareBitmap,结果我得到了一个漂亮的图像...
我知道图像的通道有问题……但我不知道该去哪里挖掘。
我假设 cvtColor
之后的 cv::Mat 是正确的......但我想查看图片创建的中间步骤。 (HSV、阈值,然后是结果)
如有任何建议,我们将不胜感激。
PS
我试过 imwrite
但没有创建文件。
更新 转换 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;
}
因为您没有 post 执行实际转换的代码 from/to SoftwareBitmap/cv::Mat.
我最好的猜测是 3 通道图像数据显示时好像有 4 通道。
好的,我找到了解决方案。
//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);