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

本文详细介绍了在Android中使用OpenCV进行图像处理的像素操作,包括像素读写、图像通道与均值方差计算、算术操作、权重叠加及归一化等。内容涵盖从Mat对象中读取像素点、行数据和全部像素,以及图像通道分离与合并、亮度和对比度调整等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文目录

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





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

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

9125154-049956510284f586.png

  • 默认情况下,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<height; row++) {
  for(int col=0; col<width; col++) {
      // 读取
      src.get(row, col, data);//!!!!!!!!!!!!!!!!!!!!!!!读取一个px
      b = data[0]&0xff;
      g = data[1]&0xff;
      r = data[2]&0xff;
      // 修改
      b = 255 - b;
      g = 255 - g;
      r = 255 - r;
      // 写入
      data[0] = (byte)b;
      data[1] = (byte)g;
      data[2] = (byte)r;
      src.put(row, col, data);
  }
}

补充诠释

  • 一个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<height; row++) {
            src.get(row, 0, data);
            /*get一整行的px数据,存进data;形象地说,是以 位置是(row, 0)的第一个px的第一个channel为起始元素,获取一个data长度的数据;
            数据一个元素(channel)一个元素(channel)地存进数组data, 每个元素是某个px的一个channel;*/
            for(int col=0; col<data.length; col++) {//行中循环列,处理内容:修改一整行的数据
                // 读取
                pv = data[col]&0xff;
                // 修改
                pv = 255 - pv;
                data[col] = (byte)pv;
            }
            // 至此,data蓄满一行修改好的px(channel)数据
            // 写入
            src.put(row, 0, data);
        }

关于代码的补充诠释

  • byte[] data = new byte[channels*width];中:
    channels 是一个px的通道数;
    width是一个行的px的个数;
  • for(int row=0; row<height; 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<data.length; 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<data.length; i++) {
  pv = data[i]&0xff;
  pv = 255-pv;
  data[i] = (byte)pv;
}
src.put(0, 0, data);

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

  • src.get(0, 0, data);get全部的px数据,存进data;
    形象地说,
    是以 位置是(0, 0)第一个px第一个channel起始元素
    获取一个data长度的数据;
    数据一个元素(channel)一个元素(channel)地存进数组data
    每个元素是某个px的一个channel
  • src.put(0, 0, data):数组对象引用赋给行首,交付全部数据;
    形象地说,
    是以 位置是(0, 0)第一个px第一个channel
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌川江雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值