Простое «размывание» массива, представляющего изображение на питоне из первых принципов - PullRequest
1 голос
/ 28 февраля 2012

У меня есть изображение, которое состоит из двух произвольно расположенных черных 1-пиксельных «шариков» на белом холсте размером 100 на 200 пикселей.Я пытаюсь «размыть эти капли, превратив некоторые соседние пиксели (в радиусе 10 пикселей от каждого шарика) в черный цвет. Я собрал следующий код, но не совсем уверен в следующем шаге ...

import numpy as np
from PIL import Image 
from scipy import ndimage
from matplotlib import pyplot
from matplotlib import cm
from scipy.misc import imsave

im = Image.open("test.png")
pix = np.asarray(im)
new_pix = np.copy(pix[:,:,0]) # need this otherwise can't write to the pix array.
pix_to_enlarge = np.where(new_pix != 255)
pixels_to_enlarge_by = 10
i=0
for each_pixel in pix_to_enlarge[0]: # this cycles through each non-white pixel
    for y in range(len(new_pix)): # this looks across the length (down) the page
        for x in new_pix[y]: # this looks across the x-axis for each y step
            radius = pixels_to_enlarge_by**2

так что я обнаружил расположение небелых пикселей в переменной pix_to_enlarge_by. Я пытаюсь (и до сих пор не могу) выбрать окружающие пиксели (в пределах 10 пикселей)и изменить их на черный тоже. Есть идеи?

Ответы [ 2 ]

5 голосов
/ 28 февраля 2012

Так или иначе, вам нужно посмотреть на каждый пиксель, а затем выяснить, какую часть этого контента вы хотите распространить между собой на каждый пиксель в вашем изображении, например, сравнивая расстояние между ними.

Вот как это делается с NumPy.Если вы хотите сделать это вручную, то это может в любом случае помочь в качестве отправной точки.Это называется свертка . 2-мерная свертка с использованием Python и NumPy

Вот хорошая отправная точка для размытия по Гауссу: http://en.wikipedia.org/wiki/Gaussian_blur

Но если вы просто хотите включить / выключить эффект размытия, тогдафункция для свертки (ядро свертки) - это просто оператор if на расстоянии между исходной точкой и любым возможным соседним пикселем.Конечно, есть оптимизация для этого случая: ваши циклы не должны будут охватывать все пиксели для всех пикселей, достаточно только для того, чтобы окружность размера R вписывалась в рассматриваемый диапазон.

Поскольку вам нужны первые принципы, здесьэто.Это работает только для черно-белых rgb

from PIL import Image 

im = Image.open("cat2.png")
px=im.load()
im2 = im.copy()
px2=im2.load()
sx,sy=im.size
def turnpixel(Nix,Niy):
    for ix in range(sx):
        for iy in range(sy):
            r2=(Nix-ix)**2+(Niy-iy)**2
            if r2<5:
                if sum(px[ix,iy])>100: # rgb sum>100 is considered ON.
                    px2[Nix,Niy]=(255,255,255)                            
                    return
                    # we turned a pixel on, so we are done with it.

for Nix in range(sx):
    for Niy in range(sy):
        px2[Nix,Niy]=(0,0,0)
        turnpixel(Nix,Niy)

im.show()
im2.show()

Если вы хотите сглаживание, которое является функцией расстояния, используйте что-то вроде

import math
def turnpixel(Nix,Niy):
    for ix in range(sx):
        for iy in range(sy):
            r=int(math.sqrt((Nix-ix)**2+(Niy-iy)**2))
            def convfunc(o,v):
                return o+int(v/(r*20+1))
            px2[Nix,Niy]=tuple(map(convfunc,px2[Nix,Niy],px[ix,iy]))
            if sum(px2[Nix,Niy])>=3*250:
                return

Очевидно, вы должны работать наплавает , а не целые числа, если вы делаете такие вещи, как это. И используйте numpy или некоторые модули управления изображениями.

Будет размытие по Гауссу (в рамках функции выше).Теперь целое число - очень плохая идея, кстати:

        inv2sigma2=1.0/(2*3)
        r2=(Nix-ix)**2+(Niy-iy)**2
        fact=inv2sigma2/(math.pi)*math.exp(-r2*inv2sigma2)
        def convfunc(o,v):
            return o+int(v*fact)
3 голосов
/ 28 февраля 2012

Стандартный способ сделать это - использовать свертку .Если вы хотите, чтобы все было черно-белым, вам нужно применить пороговое значение после выполнения свертки.

...