You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
UNI_Python/ha_07/loosen_janniclas_1540907_08.py

94 lines
3.6 KiB

import time
import numpy as np
from PIL import Image
import concurrent.futures
# Estimates the absolute area by using the composite trapezoidal rule.
# https://numpy.org/doc/stable/reference/generated/numpy.trapz.html
def calculate_area(f, a, b, num_points=10000):
x = np.linspace(a, b, num_points)
y = f(x)
area = np.trapz(np.abs(y), x)
return area
# Estimates the integral by using the composite trapezoidal rule.
# https://numpy.org/doc/stable/reference/generated/numpy.trapz.html
def calculate_integral(f, a, b, num_points=10000):
x = np.linspace(a, b, num_points)
y = f(x)
integral = np.trapz(y, x)
return integral
def mysterious_transformation(data):
y_pixel, x_pixel, _ = data.shape
data_new = np.zeros([y_pixel, x_pixel, 3], dtype=np.uint8)
for i in range(1, y_pixel - 1):
for j in range(1, x_pixel - 1):
for k in range(3):
new_value = 5 * data[i, j, k] - data[i, j - 1, k] - data[i, j + 1, k] - data[i - 1, j, k] - data[
i + 1, j, k]
data_new[i, j, k] = max(0, min(new_value, 255))
return data_new
def mysterious_transformation_parallel(data, stripes=16):
# Divide and conquer!
y_pixel, x_pixel, _ = data.shape
stripe_height = y_pixel // stripes
stripe_width = x_pixel
stripe_arrays = [data[i * stripe_height:(i + 1) * stripe_height, :] for i in range(stripes)]
def calculate(stripe, i):
y_stripe_pixel, x_stripe_pixel, _ = stripe.shape
data_new = np.zeros([y_stripe_pixel, x_stripe_pixel, 3], dtype=np.uint8)
height = i * stripe_height
width = i * stripe_width
for i in range(height, y_stripe_pixel - 1):
for j in range(width, x_stripe_pixel - 1):
for k in range(3):
# No data race is to be expected (old image is only read)
new_value = 5 * data[i, j, k] - data[i, j - 1, k] - data[i, j + 1, k] - data[i - 1, j, k] - data[i + 1, j, k]
data_new[i, j, k] = max(0, min(new_value, 255))
return data_new
i = 0
with concurrent.futures.ThreadPoolExecutor(stripes) as executor:
# Compute for each slide and resample afterward
data_new_stripes = list(executor.map(calculate, stripe_arrays, [i]))
i += 1
return np.concatenate(data_new_stripes)
img = Image.open("lokomotive.png")
pixels = np.asarray(img, dtype=np.uint8)
# Measure execution time for mysterious_transformation
# AMD Ryzen 7 5800X: 4.976848363876343 seconds
start_time_normal = time.time()
data_new_normal = mysterious_transformation(pixels)
end_time_normal = time.time()
execution_time_normal = end_time_normal - start_time_normal
print("Execution time for normal method:", execution_time_normal, "seconds")
# Measure execution time for mysterious_transformation_parallel
# Execution time for parallel method: 0.0123138427734375 seconds
start_time_parallel = time.time()
data_new_parallel = mysterious_transformation_parallel(pixels, 256)
end_time_parallel = time.time()
execution_time_parallel = end_time_parallel - start_time_parallel
print("Execution time for parallel method:", execution_time_parallel, "seconds")
# Each time one pixel is different - don't know the reason? But this difference is negligible
num_different_pixels = np.count_nonzero(np.sum(data_new_normal != data_new_parallel, axis=-1))
print("Number of different pixels:", num_different_pixels)
img_new_normal = Image.fromarray(data_new_normal, 'RGB')
img_new_normal.save("new_normal_lokomotive.png")
img_new_parallel = Image.fromarray(data_new_normal, 'RGB')
img_new_parallel.save("new_parallel_lokomotive.png")