gpt4 book ai didi

c++ - 将 cv::Mat 转换为无符号整型像素

转载 作者:行者123 更新时间:2023-11-28 01:44:17 26 4
gpt4 key购买 nike

我正在尝试将 cv::Mat 转换为 unsigned int 缓冲区图像,转换无效,我得到一个黑色图像

    Mat srcIm, edges;
srcIm = imread("15016889798859437.jpg");
cv::cvtColor(srcIm, srcIm, cv::COLOR_BGR2RGB);
unsigned int *finalSrc = new unsigned int[srcIm.rows*srcIm.cols*3];

unsigned char *input = (unsigned char*)(srcIm.data);

for (int i = 0; i < srcIm.rows; i++) {
for (int j = 0; j < srcIm.cols; j++) {
int r, g, b;
r = input[srcIm.step * j + i];
g = input[srcIm.step * j + i + 1];
b = input[srcIm.step * j + i + 2];

int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);

finalSrc[i+ j*srcIm.rows] = rgb;
}
}

cv::Mat videoFrame(srcIm.rows, srcIm.cols, CV_32SC1, finalSrc);

更新代码:

根据评论,我已经解决了错误,但我仍然得到白色图像。

unsigned int *finalSrc = new unsigned int[srcIm.rows*srcIm.cols];

unsigned char *input = (unsigned char*)(srcIm.data);

int cn = srcIm.channels();

for (int i = 0; i < srcIm.rows; i++)
{
for (int j = 0; j < srcIm.cols; j++)
{
int r, g, b;

r = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 0];
g = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 1];
b = input[(i * srcIm.cols * srcIm.channels()) + (j*srcIm.channels()) + 2];

int rgb = ((r & 0x0ff) << 16) | ((g & 0x0ff) << 8) | (b & 0x0ff);

}
}

cv::Mat videoFrame(srcIm.rows, srcIm.cols, CV_32S, finalSrc);


imshow("v", videoFrame);

最佳答案

恕我直言,有很多机会可以简化代码。

  1. 放下 cvtColor。无论如何,您要遍历元素,因此只需在循环体中交换 rb 即可避免转换。

  2. finalSrc 数组是所需大小的 3 倍。这是一个单 channel Mat,因此您只需要 srcIm.rows * srcIm.cols 元素。

  3. 不需要如此复杂的索引。 Mat 的形状相同,因此您只需遍历元素即可。

  4. 甚至不要迭代,而是使用算法——std::transform 非常适合这种情况。

  5. 不要期望能够使用 cv::imshow 可视化结果。来自文档:

    If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the value range [0,255*256] is mapped to [0,255].

    您的值使用 24 位,因此它们中的绝大多数将超过 255*256,并且会饱和为白色。

注意:我使用的是“类型化”Mat(例如 cv::Mat3bcv::Mat1i)。那些“知道”包含的数据类型,这使得它们的使用更加简单。

注意:我正在用一系列值填充输入图像。第一个像素将具有 (B=0, G=1, R=2),第二个像素将具有 (B=3, G=4, R=5),依此类推在。这使得验证结果变得简单。


代码:

#include <opencv2/opencv.hpp>
#include <numeric>

int main()
{
// Generate a sample image.
cv::Mat3b srcIm(4, 4);
std::iota(srcIm.data, srcIm.data + srcIm.rows * srcIm.cols * 3, 0);

cv::Mat1i videoFrame(srcIm.rows, srcIm.cols);

// Perform the conversion
std::transform(srcIm.begin(), srcIm.end(), videoFrame.begin()
, [](cv::Vec3b const& v) {
return v[0] | (v[1] << 8) | (v[2] << 16);
});

// Display results
for (auto const& v : videoFrame) {
std::cout << std::setw(6) << std::setfill('0') << std::hex << v << "\n";
}

return 0;
}

输出:

020100
050403
080706
0b0a09
0e0d0c
11100f
141312
171615
1a1918
1d1c1b
201f1e
232221
262524
292827
2c2b2a
2f2e2d

您提到您希望将结果作为数组。同样的原则也适用。

std::unique_ptr<unsigned int[]> result(new unsigned int[srcIm.rows * srcIm.cols]);

std::transform(srcIm.begin(), srcIm.end(), result.get()
, [](cv::Vec3b const& v) {
return v[0] | (v[1] << 8) | (v[2] << 16);
});

关于c++ - 将 cv::Mat 转换为无符号整型像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45847394/

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