C++ RGB 图像数据叠加成二维数组(向量的向量)
Posted
技术标签:
【中文标题】C++ RGB 图像数据叠加成二维数组(向量的向量)【英文标题】:C++ RGB image data overlaid into 2D array (vector of vectors) 【发布时间】:2018-05-24 09:16:44 【问题描述】:给定图像数据,我如何将 RGB 值叠加到向量向量上。从下面的代码;我有一个 uint8_t 类型的数组表示图像,然后 reinterpret_cast 将 3 字节转换为 RGB 结构,并通过 for 循环将它们放入 2D 数组中。
这可行(在屏幕截图下方)但感觉“笨拙”,有没有其他方法可以实现相同的目标? (也许通过一个迭代器到一个向量的向量,copy_n 或类似的)
#include<vector>
struct RGB
uint8_t red;
uint8_t green;
uint8_t blue;
;
int main()
std::vector<std::vector<RGB>> data;
uint8_t height, width, idx = 0, jdx = 0;
// data array representing image data - this would really be a bin fle
// header r, g, b r, g, b r, g, b r, g, b r, g, b r, g, b footer
uint8_t temp[22] = 0x02, 0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xef, 0x05, 0x0a, 0x01, 0x02, 0x0d, 0xfe, 0x00, 0x10, 0xff, 0xff, 0xef, 0xef ;
// resize data vector based on (h,w) which we get from header info
height = temp[0];
width = temp[1];
data.resize(height, std::vector<RGB>(width));
// populate the 2D data of RGB values
for (uint8_t i = 0; i<6; i++)
jdx = i % width;
data[idx][jdx] = *(reinterpret_cast<RGB*>(&temp[(2 + (i*3))]));
if (jdx == height)
idx++;
return 0;
【问题讨论】:
【参考方案1】:恕我直言,vector<vector< >>
适用于行可能具有不同长度但实际上不再称为矩阵的情况。 (OP 样本的原始数据形成了一个按行存储的矩阵。)
为什么需要将temp
数组复制到vector<>
?这是复制数据。如果可以授予生命周期,则可以直接访问 temp
。 (否则可以复制到vector<uint8_t>
。)
AFAIK,struct RGB
中的组件包装不被允许。因此,reinterpret_cast<RGB*>()
不是访问字节的最干净的方式。
所以,我想建议一个解决所有这些问题的解决方案——class Image
,它充当temp
中原始数据的包装器/访问器:
#include <cstddef>
#include <cstdint>
struct RGB
uint8_t red, green, blue;
RGB() // leaving contents uninitialized
RGB(uint8_t red, uint8_t green, uint8_t blue):
red(red), green(green), blue(blue)
;
class Image
private:
const uint8_t *_pData;
public:
class Row
private:
const uint8_t *_pData;
public:
Row(const uint8_t *pData): _pData(pData)
RGB operator[](size_t i) const
const uint8_t *pixel = _pData + 3 * i;
return RGB(pixel[0], pixel[1], pixel[2]);
;
Image(const uint8_t *pData): _pData(pData)
size_t height() const return _pData[0];
size_t width() const return _pData[1];
RGB get(size_t i, size_t j) const
const uint8_t *pixel = _pData + 2 + (i * _pData[1] + j) * 3;
return RGB(pixel[0], pixel[1], pixel[2]);
Row operator[](size_t i) const
return Row(_pData + 2 + i * _pData[1] * 3);
;
可以使用Image::get()
以及更直观的Image::operator[]()
来访问RGB 三元组。
示例代码:
#include <iomanip>
#include <iostream>
int main()
// data array representing image data - this would really be a bin fle
// header r, g, b r, g, b r, g, b footer
uint8_t temp[22] = 0x02, 0x03, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xef, 0x05,
0x0a, 0x01, 0x02, 0x0d, 0xfe, 0x00, 0x10, 0xff, 0xff, 0xef, 0xef ;
// access via
Image img(temp);
std::cout << std::hex << std::setfill('0');
// via Image::get()
std::cout << "access with img.get(i, j):\n";
for (size_t i = 0, n = img.height(); i < n; ++i)
for (size_t j = 0, m = img.width(); j < m; ++j)
RGB rgb = img.get(i, j);
std::cout << " "
<< std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.blue << std::setw(0);
std::cout << '\n';
// via Image::operator[]
std::cout << "access with img[i][j]:\n";
for (size_t i = 0, n = img.height(); i < n; ++i)
for (size_t j = 0, m = img.width(); j < m; ++j)
RGB rgb = img[i][j];
std::cout << " "
<< std::setw(2) << (unsigned)rgb.red << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.green << std::setw(0) << ' '
<< std::setw(2) << (unsigned)rgb.blue << std::setw(0);
std::cout << '\n';
return 0;
输出:
access with img.get(i, j):
01 02 03 04 05 06 07 ef 05
0a 01 02 0d fe 00 10 ff ff
access with img[i][j]:
01 02 03 04 05 06 07 ef 05
0a 01 02 0d fe 00 10 ff ff
Live Demo on coliru
【讨论】:
关于 3.,在我看来 this answer 和 this one 建议对于 POD 类型或更好的普通类型,重新解释转换版本是安全的。并不是说如果可能的话,使用更少的准系统 C++ 似乎仍然不是更好...... 非常感谢,Scheff 回应(1)图像数据将形成一个矩阵,(2)临时数组表示真正来自二进制文件的数据(如 cmets 所述,我应该更清楚),和(3)是的包装可能是一个问题,应该使用#pragma pack()对齐 @Scheff 这是一个微妙不同的问题,所以你所指的句子是关于非平凡类型的,它们通过继承是非平凡的。 @Scheff 这使得依赖你的类型成为大型项目中的 POD 很危险,IMO。如果您从 POD 继承,并且满足某些先决条件,那么突然之间看起来像 POD 并从 POD 继承的东西可能不再是 POD。struct RGB
这里满足 all data members must be in the same class, not in more than one.
并且没有继承,所以编译器不能使用填充。
@GeckoGeorge 是的,问题有点不同——我同意。不过,评论指的是r
和g
,它们都是struct RGB
的组成部分——就像在这个问题/示例中一样。以上是关于C++ RGB 图像数据叠加成二维数组(向量的向量)的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在 C++ 中将二维数组/向量作为函数参数传递? [复制]
pytorchtensor张量vector向量numpy array数组image图像RGB空间LAB空间之间相互转换大全