这个python图像模糊功能有什么问题?

mos*_*ski 5 python image-processing gaussian blur

编辑:感谢霍华德,我已经纠正了这里的代码,现在似乎正在运作.

编辑2:我已经更新了代码,以包含原始预期的垂直模糊.得到的样本输出具有各种设置:模糊比较images.jpg

模糊操作的另一个参考(Java):初学者模糊


原帖:

我正在尝试学习基本的图像处理,并在python中复制这个简单的Blur方法(第二个函数BlurHorizo​​ntal在"Reusing results"下).我知道PIL中已经存在模糊功能,但我想自己尝试基本的像素操作.

此函数应采用源图像,然后基于特定半径平均RGB像素值,并将处理后的图像写入新文件.我的问题是我得到了很多具有完全错误的平均值的像素(例如,亮绿线而不是某些区域的红色).

在模糊半径为2的情况下,平均方法将以输入像素为中心的5个像素的RGB值相加.它使用"滑动窗口"来保持运行总计,减去输出像素(左侧)并添加新的输入像素(窗口右侧).模糊方法在这里解释

示例:模糊测试图像output.jpg

我出错的任何想法?我不确定为什么图像的某些部分会干净地模糊,而其他区域则充满了与周围区域完全无关的颜色.

谢谢你的帮助.

固定工作代码(感谢霍华德)

import Image, numpy, ImageFilter
img = Image.open('testimage.jpg')

imgArr = numpy.asarray(img) # readonly

# blur radius in pixels
radius = 2

# blur window length in pixels
windowLen = radius*2+1

# columns (x) image width in pixels
imgWidth = imgArr.shape[1]

# rows (y) image height in pixels
imgHeight = imgArr.shape[0]

#simple box/window blur
def doblur(imgArr):
    # create array for processed image based on input image dimensions
    imgB = numpy.zeros((imgHeight,imgWidth,3),numpy.uint8)
    imgC = numpy.zeros((imgHeight,imgWidth,3),numpy.uint8)

    # blur horizontal row by row
    for ro in range(imgHeight):
        # RGB color values
        totalR = 0
        totalG = 0
        totalB = 0

        # calculate blurred value of first pixel in each row
        for rads in range(-radius, radius+1):
            if (rads) >= 0 and (rads) <= imgWidth-1:
                totalR += imgArr[ro,rads][0]/windowLen
                totalG += imgArr[ro,rads][1]/windowLen
                totalB += imgArr[ro,rads][2]/windowLen

        imgB[ro,0] = [totalR,totalG,totalB]

        # calculate blurred value of the rest of the row based on
        # unweighted average of surrounding pixels within blur radius
        # using sliding window totals (add incoming, subtract outgoing pixels)
        for co in range(1,imgWidth):
            if (co-radius-1) >= 0:
                totalR -= imgArr[ro,co-radius-1][0]/windowLen
                totalG -= imgArr[ro,co-radius-1][1]/windowLen
                totalB -= imgArr[ro,co-radius-1][2]/windowLen
            if (co+radius) <= imgWidth-1:
                totalR += imgArr[ro,co+radius][0]/windowLen
                totalG += imgArr[ro,co+radius][1]/windowLen
                totalB += imgArr[ro,co+radius][2]/windowLen

            # put average color value into imgB pixel

            imgB[ro,co] = [totalR,totalG,totalB]

    # blur vertical

    for co in range(imgWidth):
        totalR = 0
        totalG = 0
        totalB = 0

        for rads in range(-radius, radius+1):
            if (rads) >= 0 and (rads) <= imgHeight-1:
                totalR += imgB[rads,co][0]/windowLen
                totalG += imgB[rads,co][1]/windowLen
                totalB += imgB[rads,co][2]/windowLen

        imgC[0,co] = [totalR,totalG,totalB]

        for ro in range(1,imgHeight):
            if (ro-radius-1) >= 0:
                totalR -= imgB[ro-radius-1,co][0]/windowLen
                totalG -= imgB[ro-radius-1,co][1]/windowLen
                totalB -= imgB[ro-radius-1,co][2]/windowLen
            if (ro+radius) <= imgHeight-1:
                totalR += imgB[ro+radius,co][0]/windowLen
                totalG += imgB[ro+radius,co][1]/windowLen
                totalB += imgB[ro+radius,co][2]/windowLen

            imgC[ro,co] = [totalR,totalG,totalB]

    return imgC

# number of times to run blur operation
blurPasses = 3

# temporary image array for multiple passes
imgTmp = imgArr

for k in range(blurPasses):
    imgTmp = doblur(imgTmp)
    print "pass #",k,"done."

imgOut = Image.fromarray(numpy.uint8(imgTmp))

imgOut.save('testimage-processed.png', 'PNG')
Run Code Online (Sandbox Code Playgroud)

How*_*ard 2

我想你的线路有问题

for rads in range(-radius, radius):
Run Code Online (Sandbox Code Playgroud)

仅运行到 radius-1 (范围不包括最后一个)。将 1 添加到第二个范围参数。

更新:该行还有另一个小问题

if (co-radius-1) > 0:
Run Code Online (Sandbox Code Playgroud)

应该是

if (co-radius-1) >= 0:
Run Code Online (Sandbox Code Playgroud)