gpt4 book ai didi

android - cv::cvtColor 没有分配内存问题

转载 作者:太空宇宙 更新时间:2023-11-03 21:04:49 24 4
gpt4 key购买 nike

我正在尝试使用 cv::cvtColor 将 320x240 图像从 NV21 转换为 RGBA 图像,没有分配新内存。

所以我尝试了各种方法来实现这一目标。我知道 cv::cvtColor 调用 cv::Mat.create(..) 为输出 Mat 分配内存,而且我已经看到 cv::Mat.create(...) 仅在大小为& 请求的 Mat 类型与其当前值不同。

给定,这些,以下:

//(1)
cv::Mat frame(height + height / 2, width, CV_8UC1, pointerToNV21Data);
//(2)
cv::cvtColor(frame, frame, cv::COLOR_YUV2RGBA_NV21);

分配一个新的连续内存区域 320 * 240 * 4 channels = 307200字节(以前的空闲内存),并丢弃以前分配的 320 * 360 * 1 channel = 115200字节。

cv::cvtColor内部调用 cv::Mat.create(...) ,新的内存块被分配是因为:

  • 之前cv::cvtColor , frame 是一个 cv::Mat尺寸为 320x360,具有 1 个 channel
  • cv::cvtColor要求它是 cv::Mat尺寸为 320x240,有 4 个 channel

因此,我最乐观的尝试是执行以下操作:

//allocate a byte buffer of 307200 bytes
uchar largeBuffer[307200];

//make sure the 115200 NV21 image bytes are written to the buffer
writeNV21DataToBuffer(largeBuffer);

//create cv::Mat that wraps "largeBuffer" as a NV21 image
cv::Mat frameNV21(height + height / 2, width, CV_8UC1, largeBuffer);

//create a second cv::Mat that wraps around the same "largeBuffer",
//but this time consider it as pointing to a RGBA image
cv::Mat frameRGBA(height, width, CV_8UC4, largeBuffer);

//call cv::cvtColor
cv::cvtColor(frameNV21, frameRGBA, cv::COLOR_YUV2RGBA_NV21);

通过这样做,确实没有分配新的内存。打印cv::Mat.dataStart & cv::Mat.dataStartframeNV21 , frameRGBA之前 cv::cvtColorframeRGBAcv::cvtColor 之后确认使用了相同的内存区域,并且没有为结果分配新的内存。

但是...转换本身没有正确完成,结果显示在屏幕上时如下所示:

enter image description here

在这一点上,我没有想法。我的最后一种方法本质上是错误的,还是没有办法实现这一点?

最佳答案

是的,您可以使用 cvtColor 而无需分配新内存:只需使用更大的缓冲区:

//allocate a byte buffer of 307200 + 115200 bytes
uchar largeBuffer[307200 + 115200];

//make sure the 115200 NV21 image bytes are written to the buffer
writeNV21DataToBuffer(largeBuffer + 307200);

//create cv::Mat that wraps "largeBuffer + 307200" as a NV21 image
cv::Mat frameNV21(height + height / 2, width, CV_8UC1, largeBuffer + 307200);

//create a second cv::Mat that wraps around the same "largeBuffer",
//but this time consider it as pointing to a RGBA image
cv::Mat frameRGBA(height, width, CV_8UC4, largeBuffer);

//call cv::cvtColor
cv::cvtColor(frameNV21, frameRGBA, cv::COLOR_YUV2RGBA_NV21);

如果您的问题是:“我可以让 cvtColor 就地工作吗?”,意思是没有额外的内存来存储源位图,答案是否定的。至少不是 cvtColor

问题是您需要用cvtColor 覆盖的数据。事实上,如果一切都按顺序完成,您可以将图像的 UV 部分放在 RGBA 数据之外并保存 width * height 字节。 (Un)幸运的是,OpenCV 并行执行 cvtColor,因此您会在奇怪的地方看到错误(可能您会有一些正确转换的水平条纹和一些完全错误的水平条纹)。所以你需要有一个不同的缓冲区。

转换可以就地完成,但速度要慢得多,因为您需要重新排列数据。

关于android - cv::cvtColor 没有分配内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45606843/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com