MAT对象

MAT对象
  • Mat对象是OpenCV中用来存储图像信息的内存对象,当通过Imgcodecs.imread()方法从文件读入一个图像文件时,imread方法就会返回Mat对象实例或者通过Utils.bitmatToMat()方法由Bitmap对象转换而来,下面是图像各个像素的存储情况

  • Mat中除了存储图像的像素数据意外,还包括图片的其他属性,具体尾款、高、类型、维度、大小、深度等

加载图像与读取基本信息

1.从Android中读取图片并转换成Mat对象

//通过imread来加载图像,默认的时候,加载的是三通道 顺序为RGB的彩色图像
Mat src = Imgcodecs.imread(fileUri.getPath());
//通过下面代码来指定加载为彩色图像
//fileUri.getPath()表示路径
//第二个参数表示 加载类型,下面详细介绍:
Mat src = Imgcodecs.imread(fileUri.getPath(), Imgcodecs.IMREAD_COLOR);
加载图像类型说明
IMREAD_UNCHANGED=-1表示不改变加载图像类型,可能包含透明通道
IMREAD_GRAYSCALE=0表示加载图像为灰度图像
IMREAD_COLOR =1表示加载图像为彩色图像
  • 获取其他信息:
信息代码
宽度mat.cols()
高度mat.rows
维度mat.dims()
通道数mat.channels()
深度mat.depth()
类型mat.type()
  • 注意:通道数尤为重要,常见的通道数由1,3,4分别对应于单通道,三通道,四通道,其中四通道中通常会有透明通道的数据,图像深度表示每个通道灰度值所占大小,深度与类型密切相关:
图像深度Java中对应的数据类型
CV_8U=08位byte
CV_8S=18位byte
CV_16U=216位char
CV_16s=316位char
CV_32S=432位整型-int
CV_32F=532位float
CV_64F=664位double
  • 注意:表格中U表示无符号整数,S表示符号整数,F表示浮点数
MAT对象的创建和初始化

1.MAT对象是由头部与数据部分组成的,头部包含了一个指向数据的指针,但是Java中并没有指针的概念,所以使用数组将其替代

2.MAT内存结构:
在这里插入图片描述

3.创建MAT对象的方法:

(1)通过create()实现Mat对象的创建:
//两者都是大小3x3,类型是三通道8位无符号整数的Mat对象
Mat mat = new Mat();
mat.create(new Size(3,3), CvType.CV_8UC3);
Mat mat1 = new Mat();
mat1.create(3,3, CvType.CV_8UC3);

(2)通过ones, eye, zeros方法实现初始化创建:
Mat m1 = Mat.eye(3,3,CvType.CV_8UC3);
Mat m2 = Mat.eye(new Size(3,3), CvType.CV_8UC3);
Mat m3 = Mat.zeros(new Size(3,3), CvType.CV_8UC3);
Mat m4 = Mat.ones(new Size(3,3), CvType.CV_8UC3);

(3) 通过先定义Mat,然后通过setTo方法实现初始化(Scalar表示颜色):
Mat m1 = new Mat(3,3,CvType.CV_8UC3);
m1.setTo(new Scalar(255,255,255));

(4)通过Mat的copyTo()与clone方法实现对象的创建,Mat中的克隆和拷贝的方法会复制一份完全相同的数据一创建一个新Mat对:
Mat m1 = mew Mat(500, 500, CvType.CV_8UC3);
m1.setTo(new Scalar(127, 127, 127));
Mat cmat = m1.clone();
或者
Mat m2 = new Mat();
m1.copyTo(m2);
MAT对象的保存:
  • 创建好的Mat对象经过一系列的操作之后,可以通过OpenCV4Android的imwrite函数直接将对象保存为图像:
//创建mat对象并保存
Mat image = new Mat(500, 500, CvType.CV_8UC3);
image.setTo(new Scalar(127,127,127));
ImageSelectUtils.saveImage(image);
  • saveImage()源码分析:
File fileDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "mybook");
if(!fileDir.exists()){
    fileDir.mkdirs();
}
String name = String.valueOf(System.out.currentTImeMillis())+ "_book.jpg";
File tempFile = new FIle(fileDir.getAbsoluteFile()+File.separator, name);

//通过imwrite实现图片保存
ImgCodecs.imwrite(tempFile.getAbsolutePath(), image);
Android 中的Bitmap对象

1.图像文件与资源加载:

//在Android系统中加载图片资源,一般来说为了避免OOM我们一般将根据图片大小先进行适当的压缩,然后再进行加载:
Bitmap bitmap = Bitmap.BitmapFactory(this.getResource(), R.drawable.niuniu);

2.读写像素:

  • 获取配置信息
对于Bitmap来说,可以通过 API来获取其配置信息,在Bitmap中像素是最占用内存的部分,根据获取的长,宽, 配置信息可以计算出图像像素的大小为多少,定义一个数组来存一次性读出来的像素信息,也可以通过每次读取一个像素来循环读取。
  • Android中Bitmap像素的存储类型:
//默认情况下,Bitmap是在RGB色彩空间,A透明,R表示红色通道,G表示绿色通道,B表示蓝色通道

//表示该图像只有透明通道而没有颜色通道
Bitmap.Config.ALPHA_8;

//表示每个通道占四位,总计两个字节,表示一个像素的图像
Bitmap.Config.ARGB_4444;
//表示每个通道分别占5位,6位,5位,总计两个字节,表示一个像素的图像
Bitmap.Config.RGB_565;
//表示每个通道占8位,总计四个字节,表示一个像素的图像
Bitmap.Config.ARGB_8888;

eg: 读取并修改像素

//只有使用createBitmap的bitmap才是可以进行修改的
Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
for(int row = 0;row<bitmap1.getHeight();row++){
    for(int col = 0;col<bitmap1.getWidth();col++){
        int pixel = bitmap1.getPixel(col,row);
        //读取像素
        a = Color.alpha(pixel);
        r = Color.red(pixel);
        g = Color.green(pixel);
        b = Color.blue(pixel);
        //修改像素
        r =  127;
        g = 127;
        b = 127;
        bitmap1.setPixel(col, row, Color.argb(a, r,g,b));
    }
}
imageView.setImageBitmap(bitmap1);

//但是通过上面的方法每次读取一个像素点并设置修改,会造成对Bitmap对象的频繁访问,所以在DVM内存不紧张的时候,我们一般选用开辟出一块像素缓冲区,一次性读取全部的像素作为数组,然后循环数组访问每一个像素点,修改后再重新设置bitmap,减少对Bitmap对象的访问,速度快


int[] pixels = new int[bitmap1.getWidth() * bitmap1.getHeight()];
bitmap1.getPixels(pixels, 0, bitmap1.getWidth(), 0, 0, bitmap1.getWidth(), bitmap1.getHeight());
int a = 0, r = 0, g = 0, b = 0;
int index = 0;
for(int row = 0;row<bitmap1.getHeight();row++){
    for(int col = 0;col < bitmap1.getWidth();col++){
        index = bitmap1.getWidth() * bitmap1.getHeight() + col;
        a = (pixels[index]>>24)&0xff;
        r = (pixels[index]>>16)&0xff;
        g = (pixels[index]>>8)&0xff;
        b = (pixels[index])&0xff;


        r = 255-r;
        g = 255 -g;
        b = 255-b;
        pixels[index] = (a<<24)|(r<<16)|(g<<8)|b;
    }
}
bitmap1.setPixels(pixels,0, bitmap1.getWidth(), 0, 0, bitmap1.getWidth(), bitmap1.getHeight());

3.释放内存:

  • 创建和使用bitmap对象完成读写像素数据操作之后,需要调用bitmap.recycle()方法释放不再需要使用的Bitmap对象的内存空间,MAT对象也需要使用release()方法来释放内存,否则在进行批量处理图像或者视频的时候,就会因为MAT对象的大量创建而不释放导致的内存问题和APP崩溃
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wjxbless

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

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

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

打赏作者

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

抵扣说明:

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

余额充值