opencv2—(2)存取像素值

来源:互联网 发布:梦幻西游网络出错 编辑:程序博客网 时间:2024/04/19 12:30
从根本上说,一张图像时一个由数值组成的矩阵,这也是Opencv2用cv::Mat这个数据结构来表示图像的原因。矩阵的每个元素代表一个像素,对于灰度图像,像素有8为无符号数来表示,其中0代表黑色,255代表白色;对于彩色图象,每个像素需要三个这样的8位无符号数来表示三个颜色通道(红蓝绿)。此时矩阵的元素是一个三元数。
为了存取矩阵元素,你需要在代码中指定元素所在的行和列。程序会返回相应的元素。如果图像是单通道的,返回值是单个数值;如果图像时多通道的,返回值怎是一组向量(Vector)。
我们通过一个简单的函数俩演示直接存取像素值,该函数会在图像中加入盐噪点(随机的部分像素设置为白色或黑色),即模拟像素值丢失的情况。
一、代码
#include<iostream>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
usingnamespacestd;
usingnamespacecv;
voidsalt(Mat&image,intn)
{
       for(intk = 0; k <n; k++)
       {
              //图像的行号为j,列号为i
              inti = rand()%image.cols;
              intj = rand() %image.rows;
              //如果通道数是1,即为灰度图;如果通道数为3,即为彩色图
              if(image.channels() == 1) {
                     image.at<uchar>(j, i) = 255;
              }
              elseif(image.channels() == 3) {
                     image.at<Vec3b>(j, i)[0]= 255;
                     image.at<Vec3b>(j, i)[1]= 255;
                     image.at<Vec3b>(j, i)[2]= 255;
              }
       }
}
intmain(intargc,char**argv)
{
       MatsrcImage = imread("1.jpg");
       if(!srcImage.data)
       {
              cout<<"“1.jpg”读取失败!"<<endl;
              return0;
       }
       salt(srcImage, 3000);
       namedWindow("Image");
       imshow("Image", srcImage);
       waitKey(0);
       return0;
}

二、分析
类cv::Mat有若干成员函数可以获取图像属性。公有成员变量 cols 和 rows 给出了图像的宽和高。成员函数 at( int y, int x) 可以用来存放图像元素。但必须在编译期间知道图像的数据类型,因为 cv::Mat 可以存放任意的数据类型的元素。这也是这个函数用模板函数来实现的原因。这也意味着,当调用该函数时,你需要使用以下方式指定数据类型:
image.at<uchar>(j,i)=255;

指定的数据类型一定和矩阵中的数据类型相符合。at方法本身不会进行任何数据类型转换。
对于彩色图像,每个像素有三个通道,一个包含彩色图像的cv::Mat 会返回三个8位数组成的向量。opencv将此向量定义为cv::Vec3b,即由三个unsigned char组成的向量,所以存取彩色图像像素的代码写成以下形式:
 image.at<cv::Vec3b>(j, i)[channel]= value ;
三、扩展
cv::Mat 成员函数有时候比较麻烦,因为返回值的类型必须通过在调用时通过模板参数指定。因此,opencv提供了类cv::Mat_ ,它是cv::Mat的一个字类,此类的指针或引用可以直接进行相互类型转换。该类重载了操作符():
cv::Mat_ <uchar> im2=image; //im2指向image
im2(50,100)=0 ; //存取第50行,100列

四、测试结果

0 0
原创粉丝点击