计算机视觉 OpenCV Android | Mat像素操作(图像像素的读写、均值方差、算术、逻辑等运算、权重叠加、归一化等操作)...

本文目录

1. 像素读写
2. 图像通道与均值方差计算
3. 算术操作与调整图像的亮度和对比度
4. 基于权重的图像叠加
5. Mat的其他各种像素操作





1. 像素读写
  • Mat作为图像容器,其数据部分存储了图像的像素数据,我们可以通过相关的API来获取图像数据部分
  • 在获取图像数据的时候,知道Mat的类型通道数目关重要,
    根据Mat的类型通道数目,开辟适当大小的内存空间
    然后通过get方法就可以循环实现每个像素点值的读取、修改
    然后再通过put方法修改与Mat对应的数据部分

常见的Mat的像素读写get与put方法支持如下表:

计算机视觉 OpenCV Android | Mat像素操作(图像像素的读写、均值方差、算术、逻辑等运算、权重叠加、归一化等操作)..._第1张图片

  • 默认情况下,imread方式将Mat对象类型加载为CV_8UC3
    本系列笔记跟随原著默认提到的加载图像文件均为Mat对象、类型均为CV_8UC3、通道顺序均为BGR
  • 上表中所列举的是当前OpenCV支持的读取图像的方法;
    使用时若需要将像素值写入到Mat对象中,使用与每个get方法相对应的put方法即可。
  • 根据开辟缓存区域data数组的大小
    读写像素既可以每次从Mat中读取一个像素点数据,
    或者可以每次从Mat中读取一行像素数据,
    还可以一次从Mat中读取全部像素数据。

下面演示对Mat对象中的每个像素点的值都进行取反操作,并且分别用这三种方法实现像素操作

  • 首先要将图像加载为Mat对象
    然后获取图像的宽、高以及通道数channels(特别注意这三个值,接下来一直用到,尤其channels)
Mat src = Imgcodecs.imread(fileUri.getPath());
if(src.empty()){
  return;
}
int channels = src.channels();
int width = src.cols();
int height = src.rows();

接下来便可以通过方才所述三种方式读取像素数据、修改、写入比较它们的执行时间

1.1.从Mat中每次读取一个像素点数据

对于CV_8UC3Mat类型来说,对应的数据类型byte
则先初始化byte数组data,用来存取每次读取出来的一个像素点的所有通道值
数组的长度取决于图像通道数目

完整代码如下:

byte[] data = new byte[channels];
int b=0, g=0, r=0;
for(int row=0; row

补充诠释

  • 一个px有多个通道;
  • 一个通道配给它一个数组元素;
  • 1.2中逐行读取时的一个列(某行中的某个列其实就是一个数组元素而已)不是px,
    而只是某个px的一个channel而已;
  • 1.3 同理
  • 即1.2 以及1.3 中,data的一个元素,不是px,而只是某个px的一个channel而已;
1.2 从Mat中每次读取一行像素数据

首先需要定义每一行像素数据数组的长度,这里为图像宽度乘以每个像素的通道数目
接着循环修改每一行的数据
这里get方法第二个参数 col = 0的意思是从每一行的第一列开始获取像素数据

完整代码如下:

       // each row data
        byte[] data = new byte[channels*width];//channels 是一个px的通道数;width是一个行的px的个数;
        // loop
        int b=0, g=0, r=0;
        int pv = 0;
        for(int row=0; row

关于代码的补充诠释

  • byte[] data = new byte[channels*width];中:
    channels 是一个px的通道数;
    width是一个行的px的个数;
  • for(int row=0; row:外层 for 循环行;
  • src.get(row, 0, data);get一整行的px数据,存进data;
    形象地说,
    是以 位置是(row, 0)第一个px第一个channel起始元素
    获取一个data长度的数据;
    数据一个元素(channel)一个元素(channel)地存进数组data
    每个元素是某个px的一个channel
  • for(int col=0; col次层 for ,
    行中循环列,处理内容:修改一整行的数据;
  • 次层for执行完毕,data蓄满一行修改好的px(channel)数据;
  • src.put(row, 0, data):数组对象引用赋给行首,交付整行数据;
    形象地说,
    是以 位置是(row, 0)第一个px第一个channel起始元素
    提交一个data长度的数据,即一整行;
1.3 从Mat中一次读取全部像素数据
  • 首先定义数组长度,这里为图像宽度×图像高度×通道数目
    然后一次性获取全部像素数据,
    get的前面两个参数row=0、col=0,表示从第一个像素的第一个channel开始读取。

完整代码如下:

// all pixels
int pv = 0;
byte[] data = new byte[channels*width*height];
src.get(0, 0, data);
for(int i=0; i

关于代码的补充诠释(参考1.2的补充,不难理解)

  • src.get(0, 0, data);get全部的px数据,存进data;
    形象地说,
    是以 位置是(0, 0)第一个px第一个channel起始元素
    获取一个data长度的数据;
    数据一个元素(channel)一个<

你可能感兴趣的:(计算机视觉 OpenCV Android | Mat像素操作(图像像素的读写、均值方差、算术、逻辑等运算、权重叠加、归一化等操作)...)