【问题标题】:Copy cv::Mat into CMSampleBufferRef将 cv::Mat 复制到 CMSampleBufferRef
【发布时间】:2016-12-29 06:02:09
【问题描述】:

如何将 cv::Mat 数据复制回 sampleBuffer?

我的场景如下: 我从 pixelBuffer 创建一个 cv::Mat 用于地标检测,并将地标添加到 cv::Mat 图像数据。我想将此 cv::Mat 复制到示例缓冲区中,以便与地标一起显示。

这可能吗?

我使用 dlib 实现了这一点,但需要知道如何使用 cv::mat:

char *baseBuffer = (char *)CVPixelBufferGetBaseAddress(imageBuffer);
img.reset();
long position = 0;
while (img.move_next()) {
        dlib::bgr_pixel& pixel = img.element();
        long bufferLocation = position * 4; //(row * width + column) * 4;
        char b = baseBuffer[bufferLocation];
        char g = baseBuffer[bufferLocation + 1];
        char r = baseBuffer[bufferLocation + 2];
        dlib::bgr_pixel newpixel(b, g, r);
        pixel = newpixel;

        position++;
    }

【问题讨论】:

  • 可能是的。更多细节?一些代码?
  • 我按照 answer 将 CVImageBufferRef 转换为 cv::mat。现在我想把这个 cv::mat 放回样本缓冲区。我知道如何通过将像素复制回 sampleBuffer 来使用 dlib,但不知道如何使用 openCV 下一条评论中的 dlib 示例代码
  • 请将格式正确的代码发布到问题中。它在评论中不可读
  • 似乎代码突出显示在 cmets 中不起作用我将编辑主要问题

标签: ios opencv avfoundation


【解决方案1】:

我正在回答我自己的问题。

首先,你需要访问 cv::mat Image 的像素数据,我跟着这个很棒的solution

然后你需要从basebuffer开始将像素复制到缓冲区中。以下代码应该可以帮助您实现这一目标:

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
char *baseBuffer = (char *)CVPixelBufferGetBaseAddress(imageBuffer);   
long position = 0;
uint8_t* pixelPtr = (uint8_t*)targetImage.data;
int cn = targetImage.channels();
cv::Scalar_<uint8_t> rgbPixel;
for(int i = 0; i < targetImage.rows; i++)
{
    for(int j = 0; j < targetImage.cols; j++)
    {
        long bufferLocation = position * 4;

        rgbPixel.val[0] = pixelPtr[i*targetImage.cols*cn + j*cn + 0]; // B
        rgbPixel.val[1] = pixelPtr[i*targetImage.cols*cn + j*cn + 1]; // G
        rgbPixel.val[2] = pixelPtr[i*targetImage.cols*cn + j*cn + 2]; // R
        baseBuffer[bufferLocation] = rgbPixel.val[2];
        baseBuffer[bufferLocation + 1] = rgbPixel.val[1];
        baseBuffer[bufferLocation + 2] = rgbPixel.val[0];
        position++;
    }
}

注意事项

  • 确保您CVPixelBufferLockBaseAddress 和 CVPixelBufferUnlockBaseAddress 手术前后。我
  • 我在 CV_8UC3 上做这个,你可能想检查你的 cv::mat
    输入。
  • 我还没有进行性能分析,但是我得到了平滑的输出。

【讨论】:

  • 为什么是CV_8UC3? CMSampleBuffer本身有4个频道
  • 是的,这个方法很吃cpu,如果你的应用程序中没有很多功能那么它会很流畅,但是如果你有很多功能,那么你对cpu的使用很感兴趣
  • 对我来说worked 下一个解决方案baseBuffer[bufferLocation] = pixelPtr[i*targetImage.cols*cn + j*cn + 0]; baseBuffer[bufferLocation + 1] = pixelPtr[i*targetImage.cols*cn + j*cn + 1]; baseBuffer[bufferLocation + 2] = pixelPtr[i*targetImage.cols*cn + j*cn + 2]; 我猜是因为我使用videoOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as String) : NSNumber(value: kCVPixelFormatType_32BGRA as UInt32)]
猜你喜欢
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 2015-02-23
相关资源
最近更新 更多