OpenCV矩阵数值显示

7

问题在于:我使用OpenCV v.2.4.2加载了一张灰度图像。现在我想知道例如位置(0,0)处像素的值。我已经尝试过:

Mat image=imread("00001.jpg",1);
cvtColor(image,image,CV_RGB2GRAY);
int a=image.at<unsigned>(0,1);
printf("%d ",a);

这种方法实际上是无效的。如何使用任何数据类型(CV_8U、CV_32S等)获取像素值?

谢谢!!!


你使用的是(0,1)而不是(0,0)吗? - count0
4个回答

4
你在这里犯了两个错误。
在读取图像时,你指定了1作为输入参数。如imread所解释的那样,该函数可以以三种不同的格式读取图像。
CV_LOAD_IMAGE_UNCHANGED(<0)按原样加载图像(包括alpha通道(如果存在)) CV_LOAD_IMAGE_GRAYSCALE(0)将图像作为强度一的强度值加载 CV_LOAD_IMAGE_COLOR(>0)以RGB格式加载图像
对于你的情况,你需要使用CV_LOAD_IMAGE_GRAYSCALE作为第二个参数。
在下一步中,你使用了:image.at(0, 1);但它并不对应任何东西。你使用了unsigned,但编译器说“UNSIGNED? UNSIGNED是什么?”
我认为更好的方法是使用正确的标签,如CV_LOAD_IMAGE_COLOR或CV_LOAD_IMAGE_GRAYSCALE。在下面的例子中,我将图像读入一个通道(CV_LOAD_IMAGE_GRAYSCALE),它会自动将其转换为灰度图像。
#include <cv.h>
#include <highgui.h>

#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat gImg = imread("img.png", CV_LOAD_IMAGE_GRAYSCALE);

    uchar val;
    val = gImg.at<uchar>(0,0);

    cout << (int)val << endl;

    imshow("showImg",gImg);
    cvWaitKey(0);

    return 1;
}

好的,没错,这个可以工作,但你试过输出结果吗?在我的情况下,像素(0,0)的值是-89。当图像是8位无符号时,这怎么可能呢?接下来我想问一下,为什么要使用uchar? - Robert Kirchhoff
当然我已经尝试过了。我不知道为什么你没有正确地得到输出。我使用UCHAR正是因为@count0在上面的注释中解释的同样原因,即它可以表示0到255之间的值。 - masad
1
您不能以这种方式使用imread。第二个参数是一个标志,它可以是0、>0或<0,具体取决于您想要读取图像的灰度、3通道彩色还是原样。您无法精确指定类型。它只在特定情况下运行,因为CV_8U==0。 - Sassa
谢谢你纠正我的错误,Bob。我现在会编辑答案。 - masad

1

有一种简单的方法可以做到这一点。

MatMat.data,它提供了一个指针,指向原始数据矩阵。

要获取第n行第m列的像素值,

Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
unsigned char *input = (unsigned char*)(img.data);

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

所以,这是关于彩色图像的。对于灰度图像,

Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
Mat g;
cvtColor(img, g, CV_BGR2GRAY);
unsigned char *input = (unsigned char*)(g.data);

int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
    for(int j = 0;j < img.rows;j++){
         g = input[img.cols * j + i];
     }
 }

了解更多关于此博客文章的内容。


0

你可以尝试找出OpenCV使用的表示方式,以便更好地确定要使用的数据类型:

cout << image.depth() << ", " << image.channels() << endl;

同时也请查看关于元素访问的讨论


我知道深度和通道,但如果我知道矩阵是用于普通图像8位无符号整数的,那么矩阵就是CV_8UC1,我应该传递哪个参数到Mat :: at?确切地说是这里:image.at<???????>(0,1); - Robert Kirchhoff
CV_8UC1 表示 8 位无符号单通道,因此它将是 unsigned char,表示值从 0..255。无符号整数将表示值从 0..65536,这将是 CV_16UC1。 - count0

0
首先,没有一种通用的方法可以这样获取像素值。这意味着如果你要使用at,你必须始终指定正确类型的值。在这种情况下,你应该这样做:a = image.at<uchar>(0,1);,因为你将图像转换为8位无符号灰度(1通道)。
你还应该使用CV_BGR2GRAY而不是RGB2GRAY,因为OpenCV使用BGR作为通道顺序。
你也可以从一开始就将图像读取为灰度图像,并再次使用uchar
Mat image = imread("00001.jpg",0);    // note the 0 flag
int a=image.at<uchar>(0,1);
printf("%d ",a);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接