我们想在Android平台上开发OPenCV(处理图像);避免不了显示,通常在Android当中展示图像都是通过ImageView这个控件,当然展示的方式也有几种,在下面的内容中会简单介绍一下。但是我们在上一篇中关于Mat介绍中知道,OpenCV处理的是Mat对象,所以,为了接下来的工作更容易,我们本篇就要看一下Bitmap和Mat之间转换实现。
1 ImageView展示图像的实现方式
imageView.setImageBitmap();
imageView.setImageDrawable();
imageView.setBackground();
2 Bitmap与Mat之间转换
2.1 Utils
在OpenCV4Android的SDK中,为了开发方便,里面专门提供了两者之间的转换API Utils,下面我们就来看看这个工具类究竟有什么可以调用的接口:
static void | bitmapToMat(android.graphics.Bitmap bmp, Mat mat) Short form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false). |
static void | bitmapToMat(android.graphics.Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) Converts Android Bitmap to OpenCV Mat. |
static java.lang.String | exportResource(android.content.Context context, int resourceId) |
static java.lang.String | exportResource(android.content.Context context, int resourceId, java.lang.String dirname) |
static Mat | loadResource(android.content.Context context, int resourceId) |
static Mat | loadResource(android.content.Context context, int resourceId, int flags) |
static void | matToBitmap(Mat mat, android.graphics.Bitmap bmp) Short form of the matToBitmap(mat, bmp, premultiplyAlpha=false) |
static void | matToBitmap(Mat mat, android.graphics.Bitmap bmp, boolean premultiplyAlpha) Converts OpenCV Mat to Android Bitmap. |
从其方法列表中可以看出,其完完全全就是一个工具类,全是静态方法;且就是为了实现Mat与Bitmap转换而设计的。
现在我们就来抽取其中两个详细讲解一下:
(1)public static void bitmapToMat(android.graphics.Bitmap bmp, Mat mat, boolean unPremultiplyAlpha)
官方释义:
This function converts an Android Bitmap image to the OpenCV Mat.
'ARGB_8888' and 'RGB_565' input Bitmap formats are supported.
The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type, it keeps the image in RGBA format.
This function throws an exception if the conversion fails.
Parameters:
bmp
- is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
mat
- is a valid output Mat object, it will be reallocated if needed, so it may be empty.
unPremultiplyAlpha
- is a flag, that determines, whether the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one; this flag is ignored for 'RGB_565' bitmaps.
简译:实现Bitmap图像转Mat,支持'ARGB_8888' 和 'RGB_565'像素类型,输出的Mat类型默认是CV_8UC4类型,大小和Bitmap一样,通道顺序为RGBA。最后一个参数对于RGB_565类型Bitmap无效,当类型为ARGB_8888时,决定是否保留透明度属性。
(2)public static void matToBitmap(Mat mat, android.graphics.Bitmap bmp, boolean premultiplyAlpha)
官方释义:
This function converts an image in the OpenCV Mat representation to the Android Bitmap.
The input Mat object has to be of the types 'CV_8UC1' (gray-scale), 'CV_8UC3' (RGB) or 'CV_8UC4' (RGBA).
The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'.
This function throws an exception if the conversion fails.
Parameters:
mat
- is a valid input Mat object of types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
bmp
- is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'.
premultiplyAlpha
- is a flag, that determines, whether the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps); the flag is ignored for 'RGB_565' bitmaps.
简译:略
2.2 示例
下面就来结合示例来说明一下在实际开发中使用的流程,其实整个流程通常是设备获取图片转化为BItmap对象,调用OpenCV Utils工具类转换为Mat对象,然后对Mat经过一系列处理之后再转为Bitmap对象,通过其他的图像显示载体展示出来(我们这里就是ImageView)
关于Bitmap到Mat的转换,可以参见第一篇中搭建OpenCV开发环境最后的示例--灰度图像处理,下面主要实现Mat到Bitmap的转换,先看一下效果图。
实现的主要逻辑代码如下:
mat = mat.setTo(new Scalar(
Double.parseDouble(rtext.getText().toString()),
Double.parseDouble(gtext.getText().toString()),
Double.parseDouble(btext.getText().toString()),
Double.parseDouble(atext.getText().toString()))
);
Log.e(TAG, "generateColor: "+imageView.getHeight() );
mat.create(new Size(imageView.getWidth(), imageView.getHeight()), CvType.CV_8UC4);
//当前Mat与Bitmap转换,只支持ARGB_8888和RGB_565
Bitmap bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, bitmap,true);//添加透明度
imageView.setImageBitmap(bitmap);
有时候,我们还想把Mat对象存储为常用的图片格式,可以通过如下方式实现:
public void saveMatData(Mat mat,String filePath) {
File file = new File(filePath);
if (!file.exists()) {
file.mkdir();
}
//注意 Imgcodecs的imread()和imwrite()方法读取颜色值通道的顺序都是BGR
Imgcodecs.imwrite(filePath, mat);
}
好了,关于两者之间的转换就介绍到这里了;我们主要使用的就是Utils这个工具类,所以只要搞明白它里面的几个方法就可以了。更多内容请查看: