均值滤波
均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度g(x,y),即g(x,y)=∑f(x,y)/m m为该模板中包含当前像素在内的像素总个数。从频率域观点来看均值滤波是一种低通滤波器,高频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。
从均值滤波的定义上看,滤波操作也是进行图像卷积运算。均值滤波使用到的卷积核如下
API
public static void blur(Mat src, Mat dst, Size ksize, Point anchor, int borderType)
参数一:src,待均值滤波的图像,图像的数据类型必须是CV_8U、CV_16U、CV_16S、CV_32F和CV_64F这五种数据类型之一。
参数二:dst,均值滤波后的图像,与输入图像具有相同的尺寸和数据类型。
参数三:ksize,卷积核尺寸。
参数四:anchor,内核的基准点(锚点),其默认值为(-1,-1)代表内核基准点位于kernel的中心位置。基准点即卷积核中与进行处理的像素点重合的点,其位置必须在卷积核的内部。
参数五:borderType,像素外推法选择标志。默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。
边界填充
值
作用
BORDER_CONSTANT
0
用特定值填充,如iiiiii|abcdefgh|iiiiiii
BORDER_REPLICATE
1
两端复制填充,如aaaaaa|abcdefgh|hhhhhhh
BORDER_REFLECT
2
倒叙填充,如fedcba|abcdefgh|hgfedcb
BORDER_WRAP
3
正序填充,如cdefgh|abcdefgh|abcdefg
BORDER_REFLECT_101
4
不包含边界值倒叙填充,gfedcb|abcdefgh|gfedcba
BORDER_TRANSPARENT
5
随机填充,uvwxyz|abcdefgh|ijklmno
BORDER_REFLECT101
4
与BORDER_REFLECT_101相同
BORDER_DEFAULT
4
与BORDER_REFLECT_101相同
BORDER_ISOLATED
16
不关心感兴趣区域之外的部分
操作
/** * 均值滤波 * author: yidong * 2020/4/11 */class MeanFilterActivity : AppCompatActivity() { private lateinit var mBinding: ActivityMeanFilterBinding private lateinit var mRgb: Mat override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mBinding = DataBindingUtil.setContentView(this, R.layout.activity_mean_filter) val bgr = Utils.loadResource(this, R.drawable.lena) mRgb = Mat() Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB) bgr.release() showMat(mBinding.ivLena, mRgb) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu_mean_filter, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.menu_3_3 -> { showMat(mBinding.ivLena, mRgb) val result = Mat() Imgproc.blur(mRgb, result, Size(3.0, 3.0)) showMat(mBinding.ivResult, result) result.release() } R.id.menu_9_9 -> { showMat(mBinding.ivLena, mRgb) val result = Mat() Imgproc.blur(mRgb, result, Size(9.0, 9.0)) showMat(mBinding.ivResult, result) result.release() } R.id.menu_12_12 -> { showMat(mBinding.ivLena, mRgb) val result = Mat() Imgproc.blur(mRgb, result, Size(12.0, 12.0)) showMat(mBinding.ivResult, result) result.release() } R.id.menu_salt_pepper_noise -> { saltPepperNoiseAndMeanFilter() } R.id.menu_gaussian_noise -> { gaussianNoiseAndMeanFilter() } } return true } private fun saltPepperNoiseAndMeanFilter() { val source = mRgb.clone() val number = 10000 for (k in 0..number) { val i = (0..1000).random() % source.cols() val j = (0..1000).random() % source.rows() when ((0..100).random() % 2) { 0 -> { when (source.channels()) { 1 -> { source.put(j, i, 255.0) } 2 -> { source.put(j, i, 255.0, 255.0) } 3 -> { source.put(j, i, 255.0, 255.0, 255.0) } else -> { source.put(j, i, 255.0, 255.0, 255.0, 255.0) } } } 1 -> { when (source.channels()) { 1 -> { source.put(j, i, 0.0) } 2 -> { source.put(j, i, 0.0, 0.0) } 3 -> { source.put(j, i, 0.0, 0.0, 0.0) } else -> { source.put(j, i, 0.0, 0.0, 0.0, 0.0) } } } } } showMat(mBinding.ivLena, source) val result = Mat() Imgproc.blur(source, result, Size(9.0, 9.0)) showMat(mBinding.ivResult, result) result.release() source.release() } private fun gaussianNoiseAndMeanFilter() { val source = mRgb.clone() val noise = Mat(source.size(), source.type()) val gaussian = Mat() Core.randn(noise, 20.0, 50.0) Core.add(source, noise, gaussian) showMat(mBinding.ivLena, gaussian) val result = Mat() Imgproc.blur(gaussian, result, Size(9.0, 9.0)) showMat(mBinding.ivResult, result) source.release() noise.release() gaussian.release() result.release() } private fun showMat(view: ImageView, source: Mat) { val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888) Utils.matToBitmap(source, bitmap) view.setImageBitmap(bitmap) } override fun onDestroy() { mRgb.release() super.onDestroy() }}
效果
建议直接运行代码查看效果,更清晰更直观。
图片效果
均值滤波3X3
均值滤波9X9
均值滤波12X12
椒盐噪声和均值滤波9X9
高斯噪声和均值滤波9X9
GIF
均值滤波
源码
https://github.com/onlyloveyd/LearningAndroidOpenCV
本文分享自微信公众号 - 微卡智享(VaccaeShare)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。