pure python gaussian blur

Gerdus van Zyl gerdusvanzyl at gmail.com
Sat Aug 25 09:38:42 EDT 2007


Ok, now answering my own question :-)
Gaussian blurs can be optimized by seperating the equation and
applying in two passes.
I also implemented a version using State Vector Machines from www-
personal.engin.umd.umich.edu/~jwvm/ece581/21_GBlur.pdf but it does not
produce correct results. Most probably my fault, but it is 4x faster.
(code available on request)

Then after all this i learnt that using multiple box blurs approximate
a gaussian blur within 3%. This is the solution i use now and is fast
enough for my needs and in pure python.

Code for gaussian blur and box blur below.

~Gerdus van Zyl

Seperated Gaussian blur:

    def blurB(self):

        pixels = self.array
        temp1 = copy.copy(pixels)
        #temp2 = copy.copy(pixels)
        stride = self.width * 4

        clr = array.array('B',[255,255,255,255])

        w = self.width
        h = self.height

        def pascal(n):
            """Prints n first lines of Pascal`s triangle

            author: DR#m <dnpsite.narod.ru>
            last rev 20.03.05"""
            #n += 1

            l=[1]
            p=[]
            for i in xrange(n):
                l2=[1]
                for j in xrange(len(l)-1):
                    l2.append(l[j]+l[j+1])
                l2.append(1)
                #print l
                l=l2
            return l


        N = 5
        g = pascal(N)
        print '>',g

        gauss_fact = g
        #gauss_fact = [1,2,1]
        #gauss_fact = [1,1]
        gauss_width  = len(gauss_fact)
        s = 0
        for n in gauss_fact:
            s += n
        gauss_sum = s



        print "Pass01"
        for i in range(1,w-1):
            #print i," of ",w
            for j in range(1,h-1):
                sumr=0
                sumg=0
                sumb=0
                for k in range(0,gauss_width):
                    x = i-((gauss_width-1)>>1)+k
                    y = j
                    offset = y * stride + x * 4
                    pixel = pixels[offset:offset
+4]

                    r = pixel[0]
                    g = pixel[1]
                    b = pixel[2]

                    sumr+=r*gauss_fact[k]
                    sumg+=g*gauss_fact[k]
                    sumb+=b*gauss_fact[k]

                    clr[0] = sumr/gauss_sum
                    clr[1] = sumg/gauss_sum
                    clr[2] = sumb/gauss_sum

                    x = i
                    y = j
                    offset = y * stride + x * 4
                    temp1[offset:offset+4] =
clr

        print "Pass02"
        for i in range(1,w-1):
            #print i," of ",w
            for j in range(1,h-1):
                sumr=0
                sumg=0
                sumb=0
                for k in range(0,gauss_width):
                    x = i-((gauss_width-1)>>1)+k
                    y = j

                    offset = y * stride + x * 4
                    pixel = temp1[offset:offset+4]

                    r = pixel[0]
                    g = pixel[1]
                    b = pixel[2]

                    sumr+=r*gauss_fact[k]
                    sumg+=g*gauss_fact[k]
                    sumb+=b*gauss_fact[k]

                clr[0] = sumr/gauss_sum
                clr[1] = sumg/gauss_sum
                clr[2] = sumb/gauss_sum

                self.setPixel(i,j,clr) #to temp1


Box Blur:
    def _boxBlur(self):

        N = 5
        xsum = 0
        xsumar = []
        pixels = self.array
        opixels = copy.copy(pixels)

        stride = self.width * 4

        clr = array.array('B',[255,255,255,255])

        w = self.width
        h = self.height

        pixel = 0

        for rgb in [0,1,2]:
            for x in range(0,w):
                #print i," of ",w
                for y in range(0,h):

                    hN = N/2
                    offset = (y-hN) * stride + (x-hN) * 4
                    if offset < 0: offset = 0
                    pixel = pixels[offset+rgb]

                    xsumar.append(pixel)

                    if len(xsumar) > N:
                        xsumar = xsumar[-N:]

                    xsum = 0
                    for v in xsumar:
                        xsum += v

                    xsum /= len(xsumar)

                    pixels[offset+rgb] = xsum
        #x
        for rgb in [0,1,2]:
            for y in range(0,h):
                #print i," of ",w
                for x in range(0,w):

                    hN = N/2
                    offset = (y-hN) * stride + (x-hN) * 4
                    if offset < 0: offset = 0
                    pixel = pixels[offset+rgb]

                    xsumar.append(pixel)

                    if len(xsumar) > N:
                        xsumar = xsumar[-N:]

                    xsum = 0
                    for v in xsumar:
                        xsum += v

                    xsum /= len(xsumar)

                    pixels[offset+rgb] = xsum




More information about the Python-list mailing list