>>218707
Это gpt4 на бесплатном аккаунте, поэтому длинный ответ был обрезан, но пишет правдоподобно. Я уж не разбираюсь в этих ваших квантованиях.
# Импортируем необходимые библиотеки
import numpy as np
import cv2
import math
# Определяем функцию, которая преобразует изображение в формат YCbCr
def rgb_to_ycbcr(image):
# Создаем матрицу преобразования
matrix = np.array([[0.299, 0.587, 0.114],
[-0.1687, -0.3313, 0.5],
[0.5, -0.4187, -0.0813]])
# Добавляем смещение к компонентам Cb и Cr
offset = np.array([0, 128, 128])
# Применяем матрицу к каждому пикселю изображения
ycbcr = np.dot(image, matrix.T) + offset
# Округляем значения до целых чисел
ycbcr = np.round(ycbcr).astype(np.uint8)
# Возвращаем результат
return ycbcr
# Определяем функцию, которая преобразует изображение из формата YCbCr в RGB
def ycbcr_to_rgb(image):
# Создаем матрицу обратного преобразования
matrix = np.array([[1, 0, 1.402],
[1, -0.34414, -0.71414],
[1, 1.772, 0]])
# Убираем смещение из компонент Cb и Cr
offset = np.array([0, 128, 128])
# Применяем матрицу к каждому пикселю изображения
rgb = np.dot(image - offset, matrix.T)
# Обрезаем значения до диапазона [0, 255]
rgb = np.clip(rgb, 0, 255)
# Округляем значения до целых чисел
rgb = np.round(rgb).astype(np.uint8)
# Возвращаем результат
return rgb
# Определяем функцию, которая выполняет дискретное косинусное преобразование (DCT) над блоком 8x8
def dct(block):
# Создаем матрицу коэффициентов
c = np.zeros((8, 8))
for i in range(8):
for j in range(8):
if i == 0:
c[i, j] = 1 / math.sqrt(8)
else:
c[i, j] = math.sqrt(2 / 8) * math.cos((2 * j + 1) * i * math.pi / 16)
# Вычисляем DCT по формуле
dct = np.dot(c, np.dot(block, c.T))
# Возвращаем результат
return dct
# Определяем функцию, которая выполняет обратное дискретное косинусное преобразование (IDCT) над блоком 8x8
def idct(block):
# Создаем матрицу коэффициентов
c = np.zeros((8, 8))
for i in range(8):
for j in range(8):
if i == 0:
c[i, j] = 1 / math.sqrt(8)
else:
c[i, j] = math.sqrt(2 / 8) * math.cos((2 * j + 1) * i * math.pi / 16)
# Вычисляем IDCT по формуле
idct = np.dot(c.T, np.dot(block, c))
# Возвращаем результат
return idct
# Определяем функцию, которая квантуется блок 8x8 с помощью заданной матрицы квантования
def quantize(block, q_matrix):
# Делим каждый элемент блока на соответствующий элемент матрицы квантования
quantized = np.divide(block, q_matrix)
# Округляем значения до целых чисел
quantized = np.round(quantized).astype(np.int)
# Возвращаем результат
return quantized
# Определяем функцию, которая деквантуется блок 8x8 с помощью заданной матрицы квантования
def dequantize(block, q_matrix):
# Умножаем каждый элемент блока на соответствующий элемент матрицы квантования
dequantized = np.multiply(block, q_matrix)
# Возвращаем результат
return dequantized
# Определяем функцию, которая кодирует блок 8x8 с помощью алгоритма кодирования по длине серий (RLE)
def rle(block):
# Преобразуем блок в одномерный массив
array = block.flatten()
# Создаем список для хранения закодированных пар (значение, длина)
encoded = []
# Инициализируем текущее значение и длину
value = array[0]
length = 1
# Проходим по оставшимся элементам массива
for i in range(1, len(array)):
# Если элемент равен текущему значению, увеличиваем длину
if array[i] == value:
length += 1
# Иначе, добавляем пару (значение, длина) в список и обновляем текущее значение и длину
else:
encoded.append((value, length))
value = array[i]
length = 1
# Добавляем последнюю пару в список
encoded.append((value, length))
# Возвращаем результат
return encoded
# Определяем функцию, которая декодирует список пар (значение, длина) с помощью алгоритма RLE
def rle_decode(encoded):
# Создаем пустой список для хранения декодированных элементов
decoded = []
# Проходим по каждой паре в списке
for value, length in encoded:
# Добавляем значение в список столько раз, сколько указано длина
for i in range(length):
decoded.append(value)
# Преобразуем список в массив
decoded = np.array(decoded)
# Изменяем форму массива в блок 8x8
decoded = decoded.reshape((8, 8))
# Возвращаем результат
return decoded
# Определяем функцию, которая сжимает изображение с помощью кодека jpeg
def jpeg_compress(image, quality):
# Преобразуем изображение в формат YCbCr
ycbcr = rgb_to_ycbcr(image)
# Разделяем изображение на три канала
y, cb, cr = cv2.split(ycbcr)
# Определяем стандартную матрицу квантования для яркости
q_matrix_y = np.array([[16, 11, 10, 16, 24, 40, 51, 61],
[12, 12, 14, 19, 26, 58, 60, 55],
[14, 13, 16, 24, 40, 57, 69, 56],
[14, 17, 22, 29, 51, 87, 80, 62],
[18, 22, 37, 56, 68, 109, 103, 77],
[24, 35, 55, 64, 81, 104, 113, 92],
[49, 64, 78, 87, 103, 121, 120, 101],
[72, 92, 95, 98, 112, 100, 103, 99]])
# Определяем стандартную матрицу квантования для цветности
q_matrix_c = np.array([[17, 18, 24, 47, 99, 99, 99, 99],
[18,