Android OpenCV之基于均值实现图像二值分割
均值与标准方差
对于给定的数据,它的均值
u
u
u和
s
t
d
d
e
v
stddev
stddev计算如下:
u
=
∑
i
=
0
n
x
i
n
u = \frac{\sum_{i = 0}^n x_i}{n}
u=n∑i=0nxi
其中
n
n
n表示数据的长度、
x
i
x_i
xi表示第
i
i
i个元素的值。
s
t
d
d
e
v
=
∑
i
=
0
n
(
x
i
−
u
)
2
n
−
1
stddev=\sqrt{\frac{\sum_{i = 0}^n (x_i-u)^2}{n-1}}
stddev=n−1∑i=0n(xi−u)2
其中
n
n
n表示数据的长度、
u
u
u表示均值、1表示自由度。
OpenCV API
针对均值与标准方差,OpenCV已经在Core模块中为我们实现了这类API,具体声明如下:
meanStdDev(Mat src, MatOfDouble mean, MatOfDouble stddev)
src
表示输入的 Mat
对象。
mean
计算出的各个通道的均值,数组长度和 src
的通道数一致。
stddev
计算出的各个通道的标准方差,数组长度和 src
的通道数一致。
基于均值实现图像二值分割的代码如下
/**
* 将[srcMat]转换为灰度图像
*
* @param srcMat Mat数据源
* @return 转换后的灰度Mat
*/
fun convertMat2GrayMat(srcMat: Mat): Mat {
// 转为灰度图像
val gray = Mat()
Imgproc.cvtColor(srcMat, gray, Imgproc.COLOR_BGR2GRAY)
// 计算均值和标准方差
val means = MatOfDouble()
val stddevs = MatOfDouble()
Core.meanStdDev(gray, means, stddevs)
// 读取像素数组
val width = gray.cols()
val height = gray.rows()
val data = ByteArray(width * height)
gray.get(0, 0, data)
var pv = 0
// 根据均值进行二值分割
val average = means.toArray()[0].toInt()
for (i in data.indices) {
pv = (data[i] and 255.toByte()).toInt()
if (pv > average) {
data[i] = 255.toByte()
} else {
data[i] = 0.toByte()
}
}
gray.put(0, 0, data)
return gray
}
其中 gray
就是最后得到的二值图像,转换为Bitmap后可以在ImageView里面显示。