cv:mat 数据拷贝个unsigned char
时间: 2024-10-12 13:07:54 浏览: 33
在OpenCV (Computer Vision Library) 中,`cv::Mat` 是一个多维数组数据结构,用于表示图像数据。当你需要将 `cv::Mat` 的数据从一个类型转换为 `unsigned char` 类型,并创建一个新的副本时,可以按照以下步骤操作:
1. 首先,确保你已经有一个 `cv::Mat` 对象,比如 `src`,它包含了你需要复制的数据。
```cpp
cv::Mat src; // 假设src是一个cv::Mat对象
```
2. 使用 OpenCV 提供的 `Mat` 构造函数或成员函数将 `src` 转换为 `unsigned char` 类型的矩阵。这通常通过 `cvtColor` 函数或 `convertTo` 函数来实现,如果源数据是8位无符号整数(uchar),则不需要转换:
```cpp
cv::Mat dst(src.size(), CV_8UC1); // CV_8UC1 表示单通道、8位无符号字节类型
```
3. 如果源数据不是 `uchar` 类型,你需要使用 `convertTo` 函数来完成转换并赋值到 `dst`:
```cpp
src.convertTo(dst, CV_8UC1);
```
4. 这样,`dst` 就是一个新的 `cv::Mat` 对象,包含了 `src` 数据的副本,其中的数据类型是 `unsigned char`。
注意:这个过程会创建一个新的内存分配来存储转换后的数据,所以如果原数据量很大,可能会占用较多内存。
相关问题
opencv2 Mat数据拷贝到unsigned char*中
在OpenCV 2中,`cv::Mat` 数据结构通常用于表示图像或矩阵。如果你需要将`cv::Mat`的数据复制到无符号字符指针(unsigned char*)中,你可以通过`Mat`对象的成员函数`data()`获取矩阵元素的首地址,然后乘以每个元素占用的字节数(由`elemSize()`给出),即可得到对应区域的数据指针。
以下是一个简单的示例:
```cpp
cv::Mat img; // 假设img已经加载了图像数据
size_t size = img.total() * img.elemSize(); // 计算总字节数
unsigned char* ptr = static_cast<unsigned char*>(img.data()); // 获取像素数据地址
// 现在ptr指向了img的首字节位置,你可以遍历这个指针并访问或复制数据
for (int i = 0; i < size; ++i) {
std::cout << static_cast<char>(ptr[i]) << " "; // 打印单个像素值
}
// 如果需要复制到一个新的数组,创建一个同样大小的缓冲区,并使用memcpy等函数
unsigned char* buffer = new unsigned char[size];
std::copy(ptr, ptr + size, buffer);
```
在这个例子中,我们假设`img`是一个BGR图像,所以每个像素包含三个字节。如果想以单通道或灰度模式处理,计算的字节数可能会有所不同。
QElapsedTimer timer;// 创建计时器 timer.start(); float scale = 0.25; // default 8bits unsigned int maxPixel = 0; char *mpImgRaw; char *mpRGBBuffer; cv::Mat img_raw8(imgRawH, imgRawW, CV_8UC1); cv::Mat img_rawpixel(imgRawH, imgRawW, CV_16SC1, mpImgRaw); // 计算转换比率 for (int i = 0; i < mBitDepth; i++) maxPixel = maxPixel | (1 << i); cv::convertScaleAbs(img_rawpixel, img_raw8, 255.0 / maxPixel); // RAW8 --> 255 cv::Mat rgb(imgRawH, imgRawW, CV_8UC3); cv::cvtColor(img_raw8, rgb, cv::COLOR_BayerGR2RGB); qDebug() << "preProcess time:" << timer.elapsed() << "ms"; memcpy(mpRGBBuffer, rgb.data, rgb.cols * rgb.rows * 3); // TODO:待优化,深copy了,不做线程间为Crash QImage image((uchar *)mpRGBBuffer, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888); rimg = image;请帮我把这段代码转换成使用UMat来实现,以此来实现硬件加速
使用UMat来实现硬件加速可以通过以下步骤进行转换:
```cpp
QElapsedTimer timer;
timer.start();
float scale = 0.25; // default 8bits
unsigned int maxPixel = 0;
char *mpImgRaw;
char *mpRGBBuffer;
cv::Mat img_raw8(imgRawH, imgRawW, CV_8UC1);
cv::Mat img_rawpixel(imgRawH, imgRawW, CV_16SC1, mpImgRaw);
// 计算转换比率
for (int i = 0; i < mBitDepth; i++)
maxPixel = maxPixel | (1 << i);
cv::convertScaleAbs(img_rawpixel, img_raw8, 255.0 / maxPixel); // RAW8 --> 255
cv::Mat rgb(imgRawH, imgRawW, CV_8UC3);
cv::cvtColor(img_raw8, rgb, cv::COLOR_BayerGR2RGB);
qDebug() << "preProcess time:" << timer.elapsed() << "ms";
memcpy(mpRGBBuffer, rgb.data, rgb.cols * rgb.rows * 3); // TODO:待优化,深copy了,不做线程间为Crash
QImage image((uchar *)mpRGBBuffer, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
rimg = image;
```
转换为使用UMat的代码如下:
```cpp
QElapsedTimer timer;
timer.start();
float scale = 0.25; // default 8bits
unsigned int maxPixel = 0;
char *mpImgRaw;
char *mpRGBBuffer;
cv::UMat img_raw8(imgRawH, imgRawW, CV_8UC1);
cv::UMat img_rawpixel(imgRawH, imgRawW, CV_16SC1, mpImgRaw);
// 计算转换比率
for (int i = 0; i < mBitDepth; i++)
maxPixel = maxPixel | (1 << i);
cv::convertScaleAbs(img_rawpixel, img_raw8, 255.0 / maxPixel); // RAW8 --> 255
cv::UMat rgb(imgRawH, imgRawW, CV_8UC3);
cv::cvtColor(img_raw8, rgb, cv::COLOR_BayerGR2RGB);
qDebug() << "preProcess time:" << timer.elapsed() << "ms";
memcpy(mpRGBBuffer, rgb.getMat(cv::ACCESS_READ).data, rgb.cols * rgb.rows * 3); // TODO:待优化,深copy了,不做线程间为Crash
QImage image((uchar *)mpRGBBuffer, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
rimg = image;
```
在使用UMat时,将cv::Mat替换为cv::UMat,并使用`getMat()`方法获取UMat的底层数据进行拷贝。这样可以利用硬件加速来提高性能。
阅读全文