Integrated option for compiling to cython

This commit is contained in:
Thomas 2023-03-30 19:27:48 +02:00
parent 7a92698dfc
commit 903eb07e4b
4 changed files with 89 additions and 8 deletions

42
convolve2d_cython.pyx Normal file
View File

@ -0,0 +1,42 @@
# Import necessary packages
import cython
import numpy as np
cimport numpy as np
# Declare types for function arguments and variables
cpdef np.ndarray[np.float64_t, ndim=2] convolve2d(np.ndarray[np.float64_t, ndim=2] image,
np.ndarray[np.float64_t, ndim=2] kernel):
cdef int image_height, image_width, kernel_height, kernel_width, pad_height, pad_width, row, col
cdef np.ndarray[np.float64_t, ndim=2] padded_image, convolved_image, patch, product
# Get the dimensions of the input image and kernel
# Get the dimensions of the input image and kernel
image_height, image_width = int(image.shape[0]), int(image.shape[1])
kernel_height, kernel_width = int(kernel.shape[0]), int(kernel.shape[1])
# Compute the padding needed to handle boundary effects
pad_height = (kernel_height - 1) // 2
pad_width = (kernel_width - 1) // 2
padded_image = np.pad(image, ((pad_height, pad_height), (pad_width, pad_width)), mode='constant')
# Initialize the output image
convolved_image = np.zeros((image_height, image_width), dtype=np.float64)
# Loop over each pixel in the output image and compute the convolved value
for row in range(image_height):
for col in range(image_width):
# Extract the patch centered at the current pixel
patch = padded_image[row : row + kernel_height, col : col + kernel_width]
# Compute the element-wise product of the patch and the flipped kernel
product = patch * np.flip(kernel, axis=(0, 1))
# Compute the sum of the element-wise products
convolved_value = np.sum(product)
# Store the convolved value in the output image
convolved_image[row, col] = convolved_value
return convolved_image

View File

@ -1,11 +1,13 @@
#!//usr/bin/python3 #!//usr/bin/python3
import file_utility as file import file_utility as file
import numpyHDR as hdr import numpyHDR as hdr
import os
'''CLI application for HDR experiments''' '''CLI application for HDR experiments'''
stack = [] stack = []
select = input("Select Image Source: 1 - Raspicam, 2 - From File, 3 - Image sequence, 4 debug: ") select = input("Select Image Source: 1 - Raspicam, 2 - From File, 3 - Image sequence, 4 debug, 5 - compile Cython: ")
if int(select) == 1: if int(select) == 1:
import picamburst as pcb import picamburst as pcb
@ -36,7 +38,15 @@ if int(select) == 4:
path_list = ['webcam25_3_2023_ev0.jpg','webcam25_3_2023_ev1.jpg','webcam25_3_2023_ev2.jpg'] path_list = ['webcam25_3_2023_ev0.jpg','webcam25_3_2023_ev1.jpg','webcam25_3_2023_ev2.jpg']
stack = file.openImageList(path_list, True) stack = file.openImageList(path_list, True)
print(path_list) if int(select) == 5:
try:
os.system('python3 setup.py build_ext --inplace')
except Exception as e:
print("Error while compiling cython function", e)
print("Please restart")
exit()
#print(path_list)
#Process HDR with mertens fusion and post effects, blur #Process HDR with mertens fusion and post effects, blur
#Set last value to false for double the speed but lesser blancaed hdr effect. #Set last value to false for double the speed but lesser blancaed hdr effect.

View File

@ -1,5 +1,15 @@
import numpy as np import numpy as np
try:
import convolve2d_cython
available = True
print("Using compiled Cython Convolve")
except ImportError:
available = False
print("Using normal Numpy Convolve")
'''Numpy and PIL implementation of a Mertens Fusion alghoritm '''Numpy and PIL implementation of a Mertens Fusion alghoritm
Usage: Instantiate then set attributes: Usage: Instantiate then set attributes:
input_image = List containing path strings including .jpg Extension input_image = List containing path strings including .jpg Extension
@ -103,8 +113,13 @@ def blur(image, amount=1):
[0, -1, 0]]) [0, -1, 0]])
# Apply the kernel to each channel of the image using convolution # Apply the kernel to each channel of the image using convolution
#blurred = convolve2d(image, kernel)
kernel = kernel.astype(np.float64)
#image= image.astype(np.float64)
if available:
blurred = convolve2d_cython.convolve2d(image, kernel)
else:
blurred = convolve2d(image, kernel) blurred = convolve2d(image, kernel)
# Add the original image to the sharpened image with a weight of the sharpening amount # Add the original image to the sharpened image with a weight of the sharpening amount
sharpened = image + amount * (image - blurred) sharpened = image + amount * (image - blurred)
@ -133,12 +148,13 @@ def mertens_fusion(stack, gamma:float =1, contrast_weight:float =1 ,blurred: boo
images = [] images = []
for array in stack: for array in stack:
#Incoming arrays in 255 er range #Incoming arrays in 255 er range
img = np.array(array).astype(np.float32) / 255.0 img = np.array(array).astype(np.float64) / 255.0
img = np.power(img, gamma) img = np.power(img, gamma)
images.append(img) images.append(img)
# Compute the weight maps for each input image based on the local contrast. # Compute the weight maps for each input image based on the local contrast.
weight_maps = [] weight_maps = []
kernel = np.array([[1, 2, 1], [2, -11, 2], [1, 2, 1]])
for img in images: for img in images:
threshold_h = .99 threshold_h = .99
@ -149,7 +165,11 @@ def mertens_fusion(stack, gamma:float =1, contrast_weight:float =1 ,blurred: boo
if blurred: if blurred:
gray = blur(gray, 1) gray = blur(gray, 1)
#kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) #kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
kernel = np.array([[1, 2, 1], [2, -11, 2], [1, 2, 1]])
kernel = kernel.astype(np.float64)
if available:
laplacian = np.abs(convolve2d_cython.convolve2d(gray, kernel))
else:
laplacian = np.abs(convolve2d(gray, kernel)) laplacian = np.abs(convolve2d(gray, kernel))
weight = np.power(laplacian, contrast_weight) weight = np.power(laplacian, contrast_weight)
weight_maps.append(weight) weight_maps.append(weight)
@ -159,7 +179,7 @@ def mertens_fusion(stack, gamma:float =1, contrast_weight:float =1 ,blurred: boo
weight_maps = [w / total_weight for w in weight_maps] weight_maps = [w / total_weight for w in weight_maps]
# Compute the fused HDR image by computing a weighted sum of the input images. # Compute the fused HDR image by computing a weighted sum of the input images.
fused = np.zeros(images[0].shape, dtype=np.float32) fused = np.zeros(images[0].shape, dtype=np.float64)
for i, img in enumerate(images): for i, img in enumerate(images):
fused += weight_maps[i][:, :, np.newaxis] * img fused += weight_maps[i][:, :, np.newaxis] * img

9
setup.py Normal file
View File

@ -0,0 +1,9 @@
from setuptools import setup
from Cython.Build import cythonize
import numpy
setup(
name='convolve2d_cython',
ext_modules=cythonize("convolve2d_cython.pyx"),
include_dirs=[numpy.get_include()]
)