Skip to content
Snippets Groups Projects
Verified Commit e10065eb authored by iliya.saroukha's avatar iliya.saroukha :first_quarter_moon:
Browse files

feat: dct script seemingly done

parents
Branches
No related tags found
No related merge requests found
dct.py 0 → 100644
import argparse
import numpy as np
import numpy.typing as npt
import matplotlib.pyplot as plt
from PIL import Image
Img = npt.NDArray[np.uint8]
def load_img(path: str) -> Img:
img = Image.open(path).convert("L")
return np.array(img)
def show_image(img: Img):
if len(img.shape) == 2:
plt.imshow(img, cmap="gray", vmin=0, vmax=255)
else:
plt.imshow(img)
plt.show()
def sliding_window(img: Img, x_pos: int, y_pos: int, n: int):
sub_mat = np.zeros((n, n))
for i in range(x_pos, x_pos + n):
for j in range(y_pos, y_pos + n):
sub_mat[i - x_pos, j - y_pos] = img[i, j]
return sub_mat
def cos_mat(n: int) -> Img:
mat = np.zeros((n, n))
for i in range(n):
for j in range(n):
if i == 0:
mat[i, j] = 1 / n
else:
mat[i, j] = np.sqrt(2 / n) * np.cos((2 * j + 1) * i * np.pi \
/ (2 * n))
return mat
def dct(padded_img: Img, kernel_size: int) -> Img:
c_mat = cos_mat(kernel_size)
c_t = np.transpose(c_mat)
final_img = np.zeros(padded_img.shape)
for i in range(0, padded_img.shape[0], kernel_size):
for j in range(0, padded_img.shape[1], kernel_size):
sub_mat = sliding_window(padded_img, i, j, kernel_size)
final_img[i:i+kernel_size, j:j+kernel_size] = c_mat @ sub_mat @ c_t
return final_img
def idct(transformed_img: Img, kernel_size: int) -> Img:
c_mat = cos_mat(kernel_size)
c_t = np.transpose(c_mat)
# Compute the inverse DCT matrix
inv_c_mat = np.linalg.inv(c_mat)
inv_c_t = np.transpose(inv_c_mat)
final_img = np.zeros(transformed_img.shape)
for i in range(0, transformed_img.shape[0], kernel_size):
for j in range(0, transformed_img.shape[1], kernel_size):
sub_mat = sliding_window(transformed_img, i, j, kernel_size)
final_img[i:i+kernel_size, j:j+kernel_size] = inv_c_mat @ sub_mat @ inv_c_t
return final_img
def quantized(kernel_size: int, quality: int) -> Img:
quant = np.zeros((kernel_size, kernel_size))
for i in range(0, quant.shape[0]):
for j in range(0, quant.shape[1]):
quant[i, j] = 1 + (i + j + 1) * quality
return quant
def quantize_dct(dct_img: Img, kernel_size: int, quality: int) -> Img:
final_mat = dct_img.copy()
quant = quantized(kernel_size, quality)
for i in range(0, dct_img.shape[0], kernel_size):
for j in range(0, dct_img.shape[1], kernel_size):
final_mat[i:i+kernel_size, j:j+kernel_size] = np.round(dct_img[i:i+kernel_size, j:j+kernel_size] / quant)
return final_mat
def pad_image(img: Img, kernel_size: int):
print(img.shape)
rows, cols = img.shape
pad_rows = (kernel_size - rows % kernel_size) % kernel_size
pad_cols = (kernel_size - cols % kernel_size) % kernel_size
return np.pad(img, ((0, pad_rows), (0, pad_cols)), mode='constant', constant_values=0)
def plot_images(images, titles):
fig, axes = plt.subplots(1, 4, figsize=(12, 3)) # 1 row, 4 columns
for ax, img, title in zip(axes, images, titles):
ax.imshow(img, cmap='gray')
ax.set_title(title)
ax.axis('off')
plt.show()
def main():
parser = argparse.ArgumentParser(prog='DCT converter')
_ = parser.add_argument('filepath')
args = parser.parse_args()
kernel_size = 8
img = load_img(args.filepath)
padded = pad_image(img, kernel_size)
print(f"og shape: {img.shape}")
print(f"new shape: {padded.shape}")
dct_img = dct(padded, kernel_size)
inv_dct = idct(dct_img, kernel_size)
q_dct = quantize_dct(dct_img, kernel_size, 2)
inv_q_dct = idct(q_dct, kernel_size)
images = [dct_img, inv_dct, q_dct, inv_q_dct]
titles = ["DCT Image", "Inverse DCT", "Quantized DCT", "Inverse Quantized DCT"]
plot_images(images, titles)
if __name__ == "__main__":
main()
resources/orchid.png

601 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment