Files

94 lines
3.2 KiB
Python

import numpy as np
import cv2
import math
def dct(a: np.ndarray):
a_freq = np.zeros_like(a)
N, M = a_freq.shape[1], a_freq.shape[0]
# Iteriere über jeden Koeffizienten
for k in range(N):
for m in range(M):
dct_k_m = 0
# Iteriere über jede Position im Ortsraum
for x in range(N):
for y in range(M):
dct_k_m += a[y, x] * np.cos(k*np.pi*(2*x+1)/(2*N)) * np.cos(m*np.pi*(2*y+1)/(2*M))
dct_k_m = 4 * dct_k_m / (np.sqrt(2*N) * np.sqrt(2*M))
a_freq[m, k] = dct_k_m
return a_freq
def idct(a_freq: np.ndarray):
a = np.zeros_like(a_freq)
N, M = a_freq.shape[1], a_freq.shape[0]
a_freq = (np.sqrt(2*N) * np.sqrt(2*M)) * a_freq / 16
a_freq[0, :] = a_freq[0, :] / 2
a_freq[:, 0] = a_freq[:, 0] / 2
# Iteriere über jeden Koeffizienten
for x in range(N):
for y in range(M):
f_x_y = 0 #a_freq[0, 0] / (4)# * np.sqrt(2))
# Iteriere über jede Position im Ortsraum
for k in range(N):
for m in range(M):
f_x_y += a_freq[m, k] * np.cos(k*np.pi*(2*x+1)/(2*N)) * np.cos(m*np.pi*(2*y+1)/(2*M))
f_x_y = f_x_y / 4
a[y, x] = f_x_y
return a
def remove_dct(img, rate):
"""
Diese Implementierung wendet die diskrete Fourier Transformation auf das Bild img an. Daraufhin werden die hoch-
frequenten Anteile anteilig der Rate rate entfernt. Am Ende wird das Bild wieder in den Bildbereich transformiert.
:param img:
:param rate:
:return:
"""
assert rate <= 1, "Die Rate muss kleiner gleich 1 sein!"
height, width = img.shape
for i in range(math.ceil(width / 8)):
for j in range(math.ceil(height / 8)):
# Block extrahieren
block = np.zeros((8, 8))
horizontal_pixel, vertical_pixel = min(8, width - i * 8), min(8, height - j * 8)
block[0:vertical_pixel, 0:horizontal_pixel] = \
img[j * 8: (j * 8) + vertical_pixel, i * 8: (i * 8) + horizontal_pixel]
# In den Frequenzbereich tranformieren
block_freq = dct(block)
# Hochfrequente Anteile löschen
values_to_delete = 8 * 8 * rate
values_deleted = 0
for m in range(0, 16):
for n in range(0, m + 1):
if values_deleted >= values_to_delete:
break
if 7 - m + n < 0 or 7 - n < 0:
continue
block_freq[7 - m + n, 7 - n] = 0.
values_deleted += 1
# Rücktransformation in den Bildbereich
block = idct(block_freq)
# Einfügen in Ursprungsbild
img[j * 8: (j * 8) + vertical_pixel, i * 8: (i * 8) + horizontal_pixel] = \
block[0:vertical_pixel, 0:horizontal_pixel]
return img
''' Bild laden '''
img = cv2.imread("../../data/cameraman.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.resize(img, (160, 160))
img = (img.astype(np.float64) / 256)
cv2.imshow("ORIGINAL", img)
''' Funktion anwenden '''
img = remove_dct(img, 0.8)
''' Bild anzeigen '''
cv2.imshow("IMG", img)
cv2.waitKey(0)