将 cv::Mat 转换为无符号的 int 像素
Converting cv::Mat to unsigned int pixels
我正在尝试将cv::Mat转换为无符号的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);
恕我直言,有多种机会可以简化代码。
放下
cvtColor
.无论如何,您都在迭代元素,因此只需在循环体中交换r
和b
,就可以避免转换。finalSrc
阵列是所需大小的 3 倍。这是一个单通道Mat
,所以你只需要srcIm.rows * srcIm.cols
元素。不需要如此复杂的索引。
Mat
的形状相同,因此您可以只迭代元素。甚至不要迭代,而是使用算法 -
std::transform
非常适合这个。不要指望能够使用
cv::imshow
可视化结果。从文档中:如果图像是 16 位无符号或 32 位整数,则像素除以 256。也就是说,值范围 [0,255*256] 映射到 [0,255]。
您的值使用 24 位,因此其中绝大多数将超过
255*256
位,并将饱和为白色。
注意:我使用的是"类型化"Mat
s(例如cv::Mat3b
,cv::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++中将一个无符号的 int 转换为两个无符号的短裤?
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 从 std::vector<无符号字符>切片中提取 int?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- C++无符号短裤的划分导致 int
- 将无符号转换为复杂<int>原因符号转换警告
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 无符号的 int 到有效数字
- C++:使用没有位移位的指针将无符号字符转换为无符号 int
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- 有没有办法在C++中将mpz_t转换为 int 或无符号长 int?
- 是否可以将无符号 int 的最大值转换为 int 并将结果转换为 -1?
- 为什么QByteArray的大小是"int"而不是"无符号int"
- 为什么 (-i) 的类型(其中 i 是无符号的 int)仍然是无符号的 int?
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 如何对无符号长 int 进行位掩码?
- 使用无符号int作为二进制来在c++中实现一个集
- 这个右移是如何工作的:字符串流>>无符号的int>>无符号的int?
- 转换 int -> 无符号长 长 是否由标准定义
- 为什么在执行 int / 无符号 int 除法时使用 'divl'