访问像素值 - sumpig/OpenCV GitHub Wiki

图像本质上就是一个由数值组成的矩阵。OpenCV 使用了cv::Mat 结构来操作图像。矩阵中的每个元素表示一个像素。

对灰度图像(黑白图像)而言,像素是 8 位无符号数(数据类型为unsigned char),0 表示黑色,255 表示白色。

对彩色图像而言,每三个 8 位数值组成矩阵的一个元素。

实现

为了说明如何直接访问像素值,我们将创建一个简单的函数,用它在图像中加入椒盐噪声。

创建一个接受输入图像的函数,在函数中对图像进行修改。第二个参数是需要改成白色的像素数量。

void salt(cv::Mat image, int n) {

    // 随机数生成器
    std::default_random_engine generator;
    std::uniform_int_distribution<int> randomRow(0, image.rows - 1);
    std::uniform_int_distribution<int> randomCol(0, image.cols - 1);

    int i,j;
    for (int k=0; k<n; k++) {

        // 随机生成图形位置
        i = randomCol(generator);
        j = randomRow(generator);
 
        if (image.type() == CV_8UC1) { // 灰度图像

            image.at<uchar>(j,i)= 255; 

        } else if (image.type() == CV_8UC3) { // 彩色图像

            image.at<cv::Vec3b>(j, i) = cv::Vec3b(255, 255, 255);

            // or
            image.at<cv::Vec3b>(j,i)[0]= 255; 
            image.at<cv::Vec3b>(j,i)[1]= 255; 
            image.at<cv::Vec3b>(j,i)[2]= 255; 
        }
    }
}

原理

利用公共成员变量 colsrows可得到图像的列数和行数;

利用 cv::Mat 的 at(int x,int y) 方法可以访问元素,其中 x 是行号,y 是列号。在调用 at 方法时,你必须指定图像元素的类型。

彩色图像的每个像素对应三个部分:红色通道、绿色通道和蓝色通道,因此包含彩色图像的 cv::Mat 类会返回一个向量,向量中包含三个8 位的数值。OpenCV 为这样的短向量定义了一种类型,即 cv::Vec3b

在修改图像内容时,按值传递在复制图像时仍共享了同一块图像数据,因此图像参数没必要采用引用传递的方式。

6 种数据类型缩写:

b = unsigned char
w = unsigned short
s = short
i = int
f = float
d = double


扩展

cv::Mat_ 模板类

如果已经知道矩阵的类型,就可以使用 cv::Mat_ 类(cv::Mat 类的模板子类),它由一个 operator() 方法,可用来直接访问矩阵的元素。

因此可以这样写代码(其中 image 是一个对应uchar 矩阵的 cv::Mat 变量):

// 用Mat 模板操作图像
cv::Mat_<uchar> img(image);
img(50, 100)= 0; // 访问第50 行、第100 列处那个值
⚠️ **GitHub.com Fallback** ⚠️