有效地展平结构数组

Flatten array of structs efficiently

本文关键字:数组 结构 有效地      更新时间:2023-10-16

我正在寻找最有效的方法来展平结构数组,C++以便将扁平化一维数组数据作为输入传递给cv::Mat。结构如下所示:

struct Color3
{
uint8_t red, green, blue;
}

然后我的代码如下所示:

// Update color frame
cv::Mat colorMat = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3)
const Color3* colorPtr = colorFrame->getData(); // Get Frame from Library
std::vector<uchar> vecColorData;
data.reserve(1920 * 1080 * 3);
for (int i = 0; i < 1920 * 1080; ++i)
{
auto color = *colorPtr;
vecColorData.push_back(color.red);
vecColorData.push_back(color.green);
vecColorData.push_back(color.blue);
vecColorData++;
}
colorMat.data = vecColorData.data();

有没有比创建中间std::vector并遍历整个数组更有效的方法?我想我正在寻找类似的东西:

colorMat.data = colorFrame->getData()

但是,我收到以下错误:无法将Color3*类型的值分配给类型为uchar*的实体。

你不需要中间向量。 如果我理解,您希望为所有数据分配相同的 RGB 三元组。 我也不清楚您是否必须自己分配colorMat.data。 如果是这种情况,一旦分配了colorMat.data并将其大小调整为1920 * 1080 * 3,就可以执行以下操作:

uchar * data = colorMat.data;
for (int i = 0; i < 1920 * 1080; ++i)
{
*data++ = (uchar)colorPtr->red;
*data++ = (uchar)colorPtr->green;
*data++ = (uchar)colorPtr->.blue;
}

以下答案在技术上不是可移植的,但适用于您在现实生活中遇到的绝大多数平台。

您的Color3结构极有可能没有填充。您可以使用static_assert来验证这一点:

static_assert(sizeof(Color3) == sizeof(uint8_t) * 3);

确认后,您可以将Color3数组强制转换为uint8_t数组并将其直接传递给colorMat.data(假设成员实际上接受uint8_t(。

因此,您的代码将变为:

cv::Mat colorMat = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3)
const Color3* colorPtr = colorFrame->getData(); // Get Frame from Library
colorMat.data = reinterpret_cast<const uint8_t*>(colorPtr);

请记住,我从未使用过cv库,对数据指针的所有权要求一无所知。以上只是复制您正在做的事情,没有不必要的std::vector