put the filters in a seperate file
This commit is contained in:
parent
73bbfba24b
commit
946580320a
71
filters.py
Normal file
71
filters.py
Normal file
@ -0,0 +1,71 @@
|
||||
import logging
|
||||
|
||||
from PIL import Image, ImageFilter
|
||||
import scipy.signal
|
||||
import numpy as np
|
||||
|
||||
logging.getLogger(__name__)
|
||||
|
||||
sobel_x_kernel = np.array((
|
||||
(1, 0, -1),
|
||||
(2, 0, -2),
|
||||
(1, 0, -1)
|
||||
))
|
||||
|
||||
sobel_y_kernel = np.transpose(sobel_x_kernel)
|
||||
|
||||
def difference_of_gaussians(img: Image.Image, blur_strength_1: float | None = 1.0, blur_strength_2: float | None = 1.2) -> Image.Image:
|
||||
blur_1 = img.filter(ImageFilter.GaussianBlur(blur_strength_1))
|
||||
blur_2 = img.filter(ImageFilter.GaussianBlur(blur_strength_2))
|
||||
|
||||
w, h = img.size
|
||||
|
||||
dog = Image.new(img.mode, img.size)
|
||||
|
||||
for pixel_y in range(h):
|
||||
for pixel_x in range(w):
|
||||
|
||||
coords = (pixel_x, pixel_y)
|
||||
|
||||
p1 = blur_1.getpixel(coords)
|
||||
p2 = blur_2.getpixel(coords)
|
||||
|
||||
p1 = np.array(p1)
|
||||
p2 = np.array(p2)
|
||||
new_pixel = p2 - p1
|
||||
|
||||
dog.putpixel(coords, tuple(new_pixel.tolist()))
|
||||
|
||||
return dog
|
||||
|
||||
def sobel(img: Image.Image, gradient_threshold: int | None = 20) -> tuple[Image.Image, np.ndarray]:
|
||||
logging.debug(img.size)
|
||||
|
||||
img = img.convert('L')
|
||||
img.save('debug/test-L.png')
|
||||
|
||||
logging.debug('Sobel Operator')
|
||||
|
||||
logging.debug(img.size)
|
||||
|
||||
pixels = np.array(img)
|
||||
logging.debug(f'pixels size: {pixels.size}')
|
||||
|
||||
dx = scipy.signal.correlate(pixels, sobel_x_kernel, mode='same')
|
||||
dy = scipy.signal.correlate(pixels, sobel_y_kernel, mode='same')
|
||||
logging.debug(f'dx size: {dx.size}')
|
||||
|
||||
edges = np.sqrt(np.square(dx) + np.square(dy))
|
||||
edges[edges>255] = 255
|
||||
|
||||
logging.debug(f'edges size: {edges.size}')
|
||||
|
||||
gradient = np.arctan2(dy.flatten(), dx.flatten())
|
||||
gradient[gradient > gradient_threshold] = 0
|
||||
|
||||
pil_edges = edges.astype(np.uint8)
|
||||
newimg = Image.fromarray(pil_edges, mode='L')
|
||||
logging.debug(f'New Img Size: {newimg.size}')
|
||||
|
||||
return (newimg, gradient)
|
||||
|
||||
146
sobel.py
146
sobel.py
@ -1,19 +1,21 @@
|
||||
# import scipy.ndimage as nd
|
||||
# import imageio.v3 as iio
|
||||
# import numpy as np
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
|
||||
from PIL import Image, ImageFilter
|
||||
from PIL import Image
|
||||
import pygame as pg
|
||||
|
||||
IMAGE_PATH = 'sample-images/sunflower.jpg'
|
||||
import filters
|
||||
|
||||
FORMAT = "%(levelname)s %(filename)s - %(message)s"
|
||||
logging.basicConfig(level=logging.DEBUG, format=FORMAT)
|
||||
|
||||
IMAGE_PATH = 'sample-images/engine.PNG'
|
||||
FONT_PATH = 'fonts/scientifica.ttf'
|
||||
|
||||
BLUR_STRENGTH_1 = 1
|
||||
BLUR_STRENGTH_2 = 1.2
|
||||
|
||||
DOG_THRESHOLD = 8
|
||||
|
||||
WHITE = (255,255,255)
|
||||
|
||||
@ -49,19 +51,17 @@ def main():
|
||||
|
||||
image = Image.open(IMAGE_PATH)
|
||||
image = image.resize((image.width * RESIZE_FACTOR, image.height * RESIZE_FACTOR))
|
||||
logging.debug(f'Image Size: {image.size}')
|
||||
|
||||
L_image = image.convert('L')
|
||||
logging.debug(f'L_image Size: {L_image.size}')
|
||||
|
||||
blur_1 = image.filter(ImageFilter.GaussianBlur(BLUR_STRENGTH_1))
|
||||
blur_2 = image.filter(ImageFilter.GaussianBlur(BLUR_STRENGTH_2))
|
||||
|
||||
|
||||
print(image.size)
|
||||
dog: Image = difference_of_gaussians(blur_1, blur_2)
|
||||
dog = filters.difference_of_gaussians(image)
|
||||
logging.debug(f'Dog Size: {dog.size}')
|
||||
|
||||
dog.save('dog.png')
|
||||
|
||||
sb, gradient = sobel(dog)
|
||||
sb, gradient = filters.sobel(dog)
|
||||
|
||||
w, h = sb.size
|
||||
|
||||
@ -191,126 +191,6 @@ def main():
|
||||
pg.image.save(window, "debug/edges-render.png")
|
||||
pg.quit()
|
||||
|
||||
|
||||
|
||||
|
||||
def subtract_colors(t1: tuple, t2: tuple) -> tuple:
|
||||
|
||||
if type(t1) != tuple:
|
||||
if (t2 - t1) >= DOG_THRESHOLD:
|
||||
return t2 - t1
|
||||
else:
|
||||
return 0
|
||||
|
||||
if len(t1) != len(t2):
|
||||
print('Len of first tuple should equal second tuple probably')
|
||||
exit(1)
|
||||
|
||||
ans = []
|
||||
for i, n in enumerate(t1):
|
||||
ans.append(t2[i] - n)
|
||||
|
||||
return tuple(ans)
|
||||
|
||||
def difference_of_gaussians(blur_1: Image, blur_2: Image) -> Image:
|
||||
|
||||
w, h = blur_1.size
|
||||
|
||||
dog = Image.new(blur_1.mode, blur_1.size)
|
||||
|
||||
for pixel_y in range(0, h):
|
||||
for pixel_x in range(0, w):
|
||||
|
||||
coords = (pixel_x, pixel_y)
|
||||
|
||||
dog.putpixel(coords, subtract_colors(blur_2.getpixel(coords), blur_1.getpixel(coords)))
|
||||
|
||||
return dog
|
||||
|
||||
# Taken from
|
||||
# https://enzoftware.github.io/posts/image-filter-python
|
||||
def sobel(img: Image) -> tuple[Image.Image, list]:
|
||||
if img.mode == 'L':
|
||||
# return sobel_L(img)
|
||||
pass
|
||||
img = img.convert('RGB')
|
||||
|
||||
width, height = img.size
|
||||
|
||||
newimg = Image.new("RGB", (width, height), "white")
|
||||
gradient = [None for x in range(0, width * height)]
|
||||
for x in range(1, width - 1): # ignore the edge pixels for simplicity (1 to width-1)
|
||||
for y in range(1, height - 1): # ignore edge pixels for simplicity (1 to height-1)
|
||||
|
||||
# initialise Gx to 0 and Gy to 0 for every pixel
|
||||
Gx = 0
|
||||
Gy = 0
|
||||
|
||||
# top left pixel
|
||||
r, g, b = img.getpixel((x - 1, y - 1))
|
||||
|
||||
# intensity ranges from 0 to 765 (255 * 3)
|
||||
intensity = r + g + b
|
||||
|
||||
# accumulate the value into Gx, and Gy
|
||||
Gx += -intensity
|
||||
Gy += -intensity
|
||||
|
||||
# remaining left column
|
||||
r, g, b = img.getpixel((x-1, y))
|
||||
|
||||
Gx += -2 * (r + g + b)
|
||||
|
||||
r, g, b = img.getpixel((x-1, y+1))
|
||||
|
||||
Gx += -(r + g + b)
|
||||
Gy += (r + g + b)
|
||||
|
||||
# middle pixels
|
||||
r, g, b = img.getpixel((x, y-1))
|
||||
|
||||
Gy += -2 * (r + g + b)
|
||||
|
||||
r, g, b = img.getpixel((x, y+1))
|
||||
|
||||
Gy += 2 * (r + g + b)
|
||||
|
||||
# right column
|
||||
r, g, b = img.getpixel((x+1, y-1))
|
||||
|
||||
Gx += (r + g + b)
|
||||
Gy += -(r + g + b)
|
||||
|
||||
r, g, b = img.getpixel((x+1, y))
|
||||
|
||||
Gx += 2 * (r + g + b)
|
||||
|
||||
r, g, b = img.getpixel((x+1, y+1))
|
||||
|
||||
Gx += (r + g + b)
|
||||
Gy += (r + g + b)
|
||||
|
||||
# calculate the length of the gradient (Pythagorean theorem)
|
||||
length = math.sqrt((Gx * Gx) + (Gy * Gy))
|
||||
|
||||
# normalise the length of gradient to the range 0 to 255
|
||||
length = length / 4328 * 255
|
||||
|
||||
length = int(length)
|
||||
gradient_v = math.atan2(Gy, Gx)
|
||||
# print(gradient_v)
|
||||
|
||||
# draw the length in the edge image
|
||||
#newpixel = img.putpixel((length,length,length))
|
||||
newimg.putpixel((x,y),(length,length,length))
|
||||
if length < 20:
|
||||
gradient[y * width + x] = gradient_v
|
||||
|
||||
return (newimg, gradient)
|
||||
|
||||
def sobel_L(img: Image) -> tuple[Image.Image, list]:
|
||||
pass
|
||||
|
||||
# TODO @0x01FE : refactor plz increment by 30 & 60
|
||||
def match_gradient(n: float) -> str:
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user