OpenCV Java 二值(黑白)图像噪声滤波算法
在图像处理应用中,我们经常会遇到图像中的噪声点影响图像的分割和处理的情况,OpenCV的Java示例不多,本文给出一个OpenCV + Java环境下的图像噪声滤波算法。
OpenCV版本:3.4
Java:1.8
过滤黑白(二值)图像中的噪声点,可以指定过滤区域的大小。
算法说明:
-
输入待过滤图像(黑白二值)。
-
扩展图像(长、宽各增2),相当于在图像周围加了一圈以方便处理,减少许多的边界检测操作。
-
从第一个像素开始循环处理。
-
以指定像素为中心(同时需要考虑滤波区域的大小),提取指定区域的子图像。提取区域的大小为需过滤区域大小外加一个包围圈。
-
将所提取区域除外包围的中间部分赋值为0(黑色);
-
求子图像的均值(Core.mean());
-
如果均值不为0,则表示外包围有不为0的点(白色点),则不进行过滤。
-
如果均值为0,则表示外包围为一圈黑色点(0),则执行过滤(将原图像中间区域赋值为0)。
源码:
// 图像滤波,去除噪声点 /** * @param src - 输入的二值(黑白)图像,算法将直接修改输入图像,返回的结果也是本参数 * @param size - 需要过滤的噪声块大小,默认为以size为大小的正方形块 */ public static void noiseFilter(Mat src, int size) { // 图像高、宽 int rows = src.rows(); int cols = src.cols(); if(size < 1 || size > rows || size > cols || src.channels() != 1) { return; } // 扩展图像 Mat rslt = Mat.zeros(rows+2, cols+2, CvType.CV_8UC1); // 拷贝原图到扩展图像 Rect roi = new Rect(1, 1, cols, rows); Mat m = rslt.submat(roi); src.copyTo(m); // 滤波参数准备 Mat mCheck = Mat.zeros(size+2, size+2, CvType.CV_8UC1); Mat mMask = Mat.zeros(size, size, CvType.CV_8UC1); Rect roiCheck = new Rect(0, 0, size+2, size+2); Rect roiMask = new Rect(1, 1, size, size); Mat mRoiSrc, mRoiMask; Scalar mean; for(int i=1; i<=(rows-size+1); i++) { for(int j=1; j<=(cols-size+1); j++) { roiCheck.x = j-1; roiCheck.y = i-1; // 截取原图(实际是基于扩展后的图像操作)一部分执行检测 mRoiSrc = rslt.submat(roiCheck); // 拷贝到检测对象以免操作影响到原图 mRoiSrc.copyTo(mCheck); // 以黑点覆盖检测图像中心部分 mRoiMask = mCheck.submat(roiMask); mMask.copyTo(mRoiMask); // 求图像均值,如果不为0,则继续循环;如果为0,则执行过滤操作 mean = Core.mean(mCheck); if((byte)mean.val[0] != 0) { continue; } // 执行过滤操作 // mRoiMask为空(全黑),则以黑色小方块覆盖原图 mRoiMask = src.submat(new Rect(j-1,i-1,size,size)); mMask.copyTo(mRoiMask); } } }
|
说明:
-
所示例算法基于图像背景为黑色点(值为0),前景为白色点(值为255)计算,如果黑白反转,可方便的调整代码适应。
-
算法的效率还有改进之处,当图片比较大时,可能需要秒级的处理时间。