OpenCV现在应用很广,它是轻量级的跨平台图形库,有几百个算法,还在不断增加中,大部分是C代码,所以可以用于各种平台。
这边的需求是对很多图片的模糊化效果,但是是局部模糊而且是不规则的,一种是从上向下斜的,一种是先平的,然后再斜的,总之不是正经的矩形。
1. 搭建环境
我这里用OpenCV的Java版本来实现,首先下载OpenCV的WinPack ,因为本机是Win10,所以只需要2个文件 :
真正的功能实现在dll里,jar通过jni访问dll。如果在Linux下运行,需要下载opencv的源码编译成so文件,这个OpenCV官网有详细的步骤。
注意dll或so需要放在系统变量java.library.path所在目录下,如果在eclipse下调试可以放在这个目录下:
最后在Eclipse下的项目目录结构是:
其中TestBlur是我们的实现,Smoothing是官方的一个例子
2. 全图高斯模糊
对于OpenCV来说,这个很简单,直接看代码
// 全图模糊
public static void TestAllBlur() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("src.jpg");
Mat dst = new Mat();
Imgproc.GaussianBlur(src, dst, new Size(51, 51), 0);
Imgcodecs.imwrite("dst.jpg", dst);
}
过程是把图片读成Matirx对象,然后处理成一个新的Mat对象后保存到新的图片。前后效果比较如下:
2. 局部矩形高斯模糊
代码稍微改进一点
// 局部矩形模糊
public static void TestRectBlur() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("src.jpg");
//底部的1/6模糊
Rect rect = new Rect(0, src.height() * 5 / 6, src.width(), src.height() / 6);
// System.out.println(rect.toString());
Mat dst = src.submat(rect);
Imgproc.GaussianBlur(dst, dst, new Size(51, 51), 0);
Imgcodecs.imwrite("dst.jpg", src);
}
根据矩形获取Mat对象的区域子对象也是Mat对象,然后模糊处理,最后再保存。前后效果比较如下:
2. 局部不规则区域高斯模糊
直接处理肯定不行,需要一些变通,可以使用类似微积分的做法,把斜面区域分解成很多个并列的矩形,对每个矩形进行高斯模糊,从而实现不规则区域的模糊效果。
代码改动不大
// 斜角模糊
public static void TestDiagBlur() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("src.jpg");
//底部的2/6斜斜到底部的1/6
double _h = (double)src.height()/(6.0* src.width());//高度的步进值
for (int i = 0; i < src.width(); i++) {
//宽度为1,高度递减的矩形
Rect rect = new Rect(i, (int) (2.0*src.height()/3.0 + i * _h), 1, (int) (src.height()/3.0 - i * _h));
// System.out.println(rect.toString());
Mat dst = src.submat(rect);
Imgproc.GaussianBlur(dst, dst, new Size(51, 51), 0);
}
Imgcodecs.imwrite("dst.jpg", src);
}
最后的效果如下:
所有源码可以从Github上下载。