基本概念 图像的平滑也就是图像的模糊处理,简单但是使用频率很高,在执行许多高级处理之前都需要先进性图像的平滑处理,以提高图像处理算法效果。
平滑处理中需要使用滤波器,常用的是线性滤波器,作用是将输入像素值的加权和作为结果输出给锚点像素。
g(i,j) 为输出的锚点像素值;f(i+k,j+l) 为输入的像素值;h(k,l) 为核
滤波过程示例:
图像读入到mat
介绍平滑算法之前,先调用android自带图库,选择一张图片后返回到app中,保存在一个mat对象里。
//点击按钮,启动图库
btnLoadImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent imgPickerIntent = new Intent(Intent.ACTION_PICK);
imgPickerIntent.setType("image/*");
startActivityForResult(imgPickerIntent, REQ_CODE_PICK_IMG);
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_CODE_PICK_IMG) {
if (resultCode == RESULT_OK) {
try {
//获取图库选择的图像
final Uri imgUri = data.getData();
final InputStream inputStream = getContentResolver().openInputStream(imgUri);
//图像输入流解析为bitmap对象
final Bitmap originImg = BitmapFactory.decodeStream(inputStream);
//根据bitmap信息初始化mat对象
src = new Mat(originImg.getHeight(), originImg.getWidth(), CvType.CV_8UC4);
//将bitmap转换为mat对象
Utils.bitmapToMat(originImg, src);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
复制代码
另外,图像保存在mat对象中,所以还需要一个显示mat对象图像的方法。
private void showMat() {
//根据mat对象信息初始化bitmap
Bitmap processedImg = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
//将mat对象转换到bitmap
Utils.matToBitmap(src, processedImg);
//显示
imgProcess.setImageBitmap(processedImg);
}
复制代码
均值模糊
使用归一化块滤波器,也是最简单的滤波器,输出像素值是核窗口内像素的均值,即所有像素加权系数相等。
核如下:
opencv-android sdk 提供的方法如下
/**
* 均值模糊
* @param src 源图像mat
* @param dst 目标图像mat
* @param ksize 核大小
*/
public static void blur(Mat src, Mat dst, Size ksize)
{
//sdk封装的一个jni方法,具体的实现在.so库中用c/c++实现
blur_2(src.nativeObj, dst.nativeObj, ksize.width, ksize.height);
return;
}
复制代码
方法使用如下:
Imgproc.blur(src, src, new Size(3, 3));
showMat();
复制代码
高斯模糊
高斯滤波器是最有用的滤波器(不是最快),将输入的每一个像素点与高斯内核的卷积核作为输出像素值。
高斯模糊中,距离锚点像素越近的输入像素权重越高,即临近锚点像素对像素结果的影响比那些较远的像素要高。
高斯核是通过高斯函数获得的
opencv-android sdk 提供的方法如下
//javadoc: GaussianBlur(src, dst, ksize, sigmaX)
public static void GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX)
{
//sdk封装的一个jni方法,具体的实现在.so库中用c/c++实现
GaussianBlur_2(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, sigmaX);
return;
}
复制代码
方法使用
Imgproc.GaussianBlur(src, src, new Size(3, 3), 0);
showMat();
复制代码
中值滤波
中值滤波是将图像的每个像素用邻域像素的中值代替。
opencv-android sdk 提供的方法如下
//javadoc: medianBlur(src, dst, ksize)
public static void medianBlur(Mat src, Mat dst, int ksize)
{
medianBlur_0(src.nativeObj, dst.nativeObj, ksize);
return;
}
复制代码
方法使用
Imgproc.medianBlur(src, src, 3);
showMat();
复制代码
总结
这里简单介绍了几种滤波器和opencv对应的方法,并在android下进行了简单使用,具体的代码可以参见demo
另外,也知道了,opencv-android sdk 的方法其实都是jni封装的c/c++的实现,sdk中也没有什么注释,但是方法的参数和作用是和c/c++保持一致的,所以阅读opencv官网上的开发文档即可(部分章节有java的示例和说明)。