我试图将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);
答案 0 :(得分:2)
恕我直言,有很多机会可以简化代码。
放弃cvtColor
。无论如何,你正在遍历元素,所以只需在循环体中交换r
和b
,就可以避免转换。
finalSrc
数组是所需大小的3倍。它是单个频道Mat
,因此您只需要srcIm.rows * srcIm.cols
元素。
不需要这么复杂的索引。 Mat
s的形状相同,因此您可以迭代元素。
甚至不进行迭代,而是使用算法 - 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);
});