C++ 着色16位灰度垫只产生一半的图像

C++ 着色16位灰度垫只产生一半的图像,c++,objective-c,opencv,image-processing,colors,C++,Objective C,Opencv,Image Processing,Colors,我已经获得了一个16位灰度矩阵(Mat type=CV_16UC1),我想使用OpenCV和存储在整数数组中的自定义colormap渐变对其进行着色。colormap包含256种RGB颜色,格式如下: const int colormap[] = {R0, G0, B0, R1, G1, B1, ..., R255, G255, B255}; 灰度矩阵每个像素点包含一个无符号字符(0到255之间),我使用它作为索引,在colormap数组中查找相应的RGB颜色 新的彩色Mat初始化为全黑色,尺

我已经获得了一个16位灰度矩阵(Mat type=CV_16UC1),我想使用OpenCV和存储在整数数组中的自定义colormap渐变对其进行着色。colormap包含256种RGB颜色,格式如下:

const int colormap[] = {R0, G0, B0, R1, G1, B1, ..., R255, G255, B255};
灰度矩阵每个像素点包含一个无符号字符(0到255之间),我使用它作为索引,在
colormap
数组中查找相应的RGB颜色

新的彩色Mat初始化为全黑色,尺寸与灰度Mat相同,但它是一个3通道矩阵

cv::Mat colorizedMat = cv::Mat::zeros(matGreyScale.rows, matGreyScale.cols, CV_16UC3);
然后,我使用下面的代码在
colorizedMat
的每个像素上循环,并使用从
colormap
获得的RGB值对其进行更新:

for (int row = 0; row < colorizedMat.rows; row++){
    for (int col = 0; col < colorizedMat.cols; col++) {
        int pixelVal = matGreyScale.at<uchar>(cv::Point(col,row));
        cv::Vec3b color(colormap[pixelVal*3+2],colormap[pixelVal*3+1],colormap[pixelVal*3]);
        colorizedMat.at<cv::Vec3b>(cv::Point(col,row)) = color;
    }
}
for(int row=0;row
但是,这导致
彩色化标记只填充了大约一半,而另一半完全为黑色,如下所示。图像似乎也有点拉长

原始灰度图像:彩色图像:

如果我将内部for循环的边界更改为
col
,则整个Mat会着色,但是图像会非常拉伸

如何使用自定义颜色贴图为灰度垫子正确着色?非常感谢您的帮助


这些图像很小,因为我接收它们的相机分辨率为80x60。

我不熟悉OpenCV。但我觉得你打电话的顺序不对

更改您的代码,如:

Point(row,col)

可能有帮助,可能没有。

问题是您声明的
colorizedMat
深度不正确:

cv::Mat colorizedMat = cv::Mat::zeros(matGreyScale.rows, matGreyScale.cols, CV_16UC3);
它应该是
CV_8UC3
,而不是
CV_16UC3
。由于
Vec3b
Vec
相同,因此只能使用命令更新一半的
colorizedMat.data

colorizedMat.at<cv::Vec3b>(cv::Point(col,row)) = color;
我看到了一些问题

  • 您的
    matGreyScale
    已声明为CV_16UC1。但是,您尝试使用
    matGreyScale.at(cv::Point(col,row))访问它的元素。这是不正确的,因为CV_16UC1应该使用(…)上的
    matGreyScale.at来访问。它令人困惑,因为
    CV_16UC1
    听起来像“unsigned char”,但实际上是“16位,unsigned,channels=1”。见:

  • 如果将
    colorizedMat
    声明为
    CV_16UC3
    ,则应创建
    Vec3s
    类型的向量以填充此矩阵。或者,您可以按照上面Q.H.的建议,将
    colorizedMat
    声明为
    CV_8UC3
    ,并坚持创建
    Vec3b
    类型的向量(这在将彩色映射数据缩放为0-255时更有意义)。见:


  • x
    坐标将是列编号,
    y
    坐标将是行,因此OP代码中参数的顺序是正确的。另外,如果这两个图像被交换,图像将被转置,而不是简单地切成两半。谢谢你的提示和链接。我使用vec3声明向量,并以这种方式填充矩阵,然后返回全宽度矩阵
    colorizedMat.at<cv::Vec3b>(cv::Point(col,row)) = color;
    
    const uchar colormap[] = {R0, G0, B0, R1, G1, B1, ..., R255, G255, B255};