椒盐噪声
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。椒盐噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。椒盐噪声是指两种噪声:盐噪声(salt noise)及椒噪声(pepper noise)。盐噪声一般是白色噪声,椒噪声一般是黑色噪声,前者高灰度噪声,后者属于低灰度噪声,一般两种噪声同时出现,呈现在图像上就是黑白杂点。
API
目前为止OpenCV 4中没有提供专门用于为图像添加椒盐噪声的函数。但是可以根据对椒盐的理解来手动生成。步骤如下图。
操作
随着噪点数量的上升,添加噪声过程耗时也会增加。为了防止ANR,可自行考虑异步处理。
/**
* 椒盐噪声
* author: yidong
* 2020/3/31
*/
class SaltPepperNoiseActivity : AppCompatActivity() {
companion object {
fun launch(context: Context) {
val intent = Intent(context, SaltPepperNoiseActivity::class.java)
context.startActivity(intent)
}
}
private lateinit var mBinding: ActivitySaltPepperNoiseBinding
private lateinit var mRgb: Mat
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_salt_pepper_noise)
mBinding.presenter = this
val bgr = Utils.loadResource(this, R.drawable.lena)
mRgb = Mat()
Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
showMat(mBinding.ivLena, mRgb)
}
fun addNoise() {
hideKeyboard()
val source = mRgb.clone()
var number = 10000
try {
number = mBinding.etNoiseNumber.text.toString().toInt()
} catch (e: NumberFormatException) {
}
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.ivResult, source)
source.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)
}
private fun hideKeyboard() {
val inputMethodManager =
this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(
mBinding.ivLena.windowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}
override fun onDestroy() {
mRgb.release()
super.onDestroy()
}
}