РЕДАКТИРОВАТЬ : Благодаря Говарду я исправил здесь код, и он, кажется, работает сейчас.
РЕДАКТИРОВАТЬ * : я обновил кодвключить вертикальное размытие, как первоначально предполагалось.Результирующий пример вывода с различными настройками: Сравнение размытия images.jpg
Еще один справочник по операциям размытия (Java): Размытие для начинающих
оригинальный пост:
Я пытаюсь узнать об основной обработке изображений и продублировать этот простой Blur метод (вторая функция BlurHor Horizontal в разделе «Повторное использование результатов») в Python.Я знаю, что в PIL уже есть функции размытия, но я хочу сам опробовать основные пиксельные операции.
Эта функция должна взять исходное изображение, затем усреднить значения пикселей RGB на основе определенного радиуса и записать обработанныеизображение в новый файл.Моя проблема в том, что я получаю много пикселей с совершенно неправильными усредненными значениями (например, ярко-зелеными линиями вместо красных в определенных областях).
При радиусе размытия 2 метод усреднения складываетсязначения RGB для 5 пикселей с центром на входном пикселе.Он использует «скользящее окно» для сохранения промежуточного итога, вычитая исходящий пиксель (левая сторона) и добавляя новый входящий пиксель (правая сторона окна). Метод размытия, описанный здесь
Пример: Вывод тестового изображения размытия. 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')