小言_互联网的博客

在OpenCV里实现均值平滑2

492人阅读  评论(0)

通过均值可以实现平滑的效果,不过这样采用卷积的方式来计算还是不够快,即使是使用了分离的卷积计算。由于均值的特殊性,可以针对这种卷积计算进行优化。我们知道计算均值就是把所有元素加到一起,然后再除以个数。由于图像很大,而卷积算子很小,那么就相当于一个窗口不断地滑动在图像上,并且计算这个窗口的和,那么有没有方法让这个计算的和快速一些。我们知道卷积计算是由乘法再求和,要快速就得把乘法替换掉,那么要怎么样才替换掉呢?这里就得引入一个技巧性的计算方法—积分图像(Integral Image)。图像是由一系列的离散像素点组成, 因此图像的积分其实就是求和. 图像积分图中每个点的值是原图像中该点左上角的所有像素值之和。首先建立一个数组 A 作为积分图像,其宽高与原图像相等。 然后对这个数组赋值,每个点存储的是该点与图像原点所构成的矩形中所有像素的和。如下图来说明计算:

在这里左边是输入图像,右边是积分图像。为了计算方便,一般积分图像需要在原图的大小上面和左边补充一行0的元素,这样采用公式计算就方便。在原图里(1,1)的位置是1,在积分图像里,就变成(2,2)的位置,然后来看一下(2,2)左上角所有元素只有一个(1,1),即是1。计算积分图(2,3)的位置时,那么查看原图里左上角所有元素是(1,1),(1,2),即是1+5,因此等于6。计算积分图(3,2)位置,这个左上角的元素是(1,1),(2,1),即是1+2=3,所以(3,2)位置值等于3。计算积分图(3,3)位置,就是计算原图里(1,1)、(1,2)、(2,1)、(2,2)元素之和,即是1+5+2+4=12。通过这样的方式,就可以计算出积分图像,就像右边的图像一样。

有了这样的积分图像,再来计算均值,就容易得多了,并且无论计算那一点的均值都是常量时间,无须考虑窗口的大小。如下图这样使用:

左边是输入图像,右边是该图像的积分图像,现在要计算原图选中的像素之和,那么可以这样计算,找到这个区域对应积分图像的四个坐标,再把坐标左上角的值按这样计算:46 – 22 – 20 + 10 = 14。

从这个图里看到就更加明显,要计算A的面积,就是L4-L2-L3+L1。

在这里引入快速计算积分图像的方法,如下图:

可以看到上面计算公式:Integral(i,j) = Integral(i,j-1) + ColumnSum(j);

这样只需要计算原图像上列积分,再加上积分图像左边的元素值即可。由此可见可见,可以通过这个公式快速地计算积分图像,实现的代码如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import cv2
import numpy as np

#计算积分图像Integral(i,j) = Integral(i,j-1) + ColumnSum(j);
def integral(img,h,w):
    integ_graph = np.zeros((h+1,w+1),dtype = np.int32)
    for x in range(h):
        sum_clo = 0
        for y in range(w):
            sum_clo +=  img[x][y]
            #print('y={},{},sum={}'.format(y,img[x][y],sum_clo))
            integ_graph[x+1][y+1] = integ_graph[x][y+1] + sum_clo;
    return integ_graph

#测试1
image1=np.array([[1,5,1],[2,4,1]])
h,w = image1.shape[:2]
print('imagesize={}-{}'.format(w,h))

print(image1)
print(integral(image1,h,w))

#测试2
image2=np.array([[1,2,2,4,1],
                 [3,4,1,5,2],
                 [2,3,3,2,4],
                 [4,1,5,4,6],
                 [6,3,2,1,3]])
h,w = image2.shape[:2]
print('imagesize={}-{}'.format(w,h))

print(image2)
print(integral(image2,h,w))

cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

imagesize=3-2

[[1 5 1]

 [2 4 1]]

[[ 0  0  0  0]

 [ 0  1  6  7]

 [ 0  3 12 14]]

imagesize=5-5

[[1 2 2 4 1]

 [3 4 1 5 2]

 [2 3 3 2 4]

 [4 1 5 4 6]

 [6 3 2 1 3]]

[[ 0  0  0  0  0  0]

 [ 0  1  3  5  9 10]

 [ 0  4 10 13 22 25]

 [ 0  6 15 21 32 39]

 [ 0 10 20 31 46 59]

 [ 0 16 29 42 58 74]]

https://blog.csdn.net/caimouse/article/details/51749579

 


转载:https://blog.csdn.net/caimouse/article/details/100894310
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场