Video siqish algormlarini Python'dan boshlab tushunish va amalga oshirish bo'yicha keng qamrovli qo'llanma. Zamonaviy video kodeklar asosidagi nazariya va amaliyotni o'rganing.
Python'da Video Kodekini Yaratish: Siqish Algormlariga Chuqur Kirish
Bizning yuqori ulanishli dunyomizda video qirol hisoblanadi. Streaming xizmatlaridan tortib, video konferensiyalar va ijtimoiy tarmoq lentasigacha, raqamli video internet trafigini egallaydi. Ammo yuqori aniqlikdagi filmni standart internet ulanishi orqali yuborish qanday mumkin? Javob ajoyib va murakkab sohada yotadi: video siqish. Ushbu texnologiyaning yuragida video kodek (COder-DECoder) turadi, bu fayl hajmini vizual sifatni saqlab qolgan holda sezilarli darajada kamaytirish uchun mo'ljallangan murakkab algormlar to'plamidir.
H.264, HEVC (H.265) va bepul AV1 kabi sanoat standartidagi kodeklar juda murakkab muhandislik namunasi bo'lsa-da, ularning asosiy tamoyillarini tushunish har qanday ishtiyoqli dasturchi uchun ochiqdir. Ushbu qo'llanma sizni video siqish dunyosiga chuqur sayohatga olib boradi. Biz shunchaki nazariya haqida gaplashmaymiz; biz Python yordamida soddalashtirilgan, ta'limiy video kodekni boshidan oxirigacha qurib chiqamiz. Ushbu amaliy yondashuv zamonaviy video streamingni mumkin qiladigan oqlangan g'oyalarni tushunishning eng yaxshi usuli hisoblanadi.
Nima uchun Python? Haqiqiy vaqt rejimida, yuqori samarali tijoriy kodeklar (odatda C/C++ yoki hatto assembly tilida yozilgan) uchun ishlatiladigan til bo'lmasa-da, Pythonning o'qilishi va NumPy, SciPy va OpenCV kabi kuchli kutubxonalari uni o'rganish, prototip yaratish va tadqiqotlar uchun mukammal muhitga aylantiradi. Siz past darajadagi xotira boshqaruviga tushib qolmasdan, algorimlarga e'tibor qaratishingiz mumkin.
Video Siqishning Asosiy Tushunchalarini Tushunish
Birinchi qator kodni yozishdan oldin, biz nima qilishimiz kerakligini tushunishimiz kerak. Video siqishning maqsadi ortiqcha ma'lumotlarni yo'q qilishdir. Xom, siqilmagan video ulkan hajmdadir. Bir daqiqalik 1080p video sekundiga 30 kadr tezlikda 7 GB dan oshishi mumkin. Ushbu ma'lumotlar hayvonini jilovlash uchun biz ikkita asosiy turdagi ortiqchalikdan foydalanamiz.
Siqishning Ikki Ustuni: Fazoviy va Vaqtinchalik Ortiqchalik
- Fazoviy (Ramka ichidagi) Ortiqchalik: Bu bitta ramka ichidagi ortiqchalikdir. Katta ko'k osmon yoki oq devorning bir qismini tasavvur qiling. Ushbu hududdagi har bir piksel uchun rang qiymatini saqlash o'rniga, biz uni yanada samaraliroq tasvirlashimiz mumkin. Bu JPEG kabi tasvirni siqish formatlari orqasidagi bir xil tamoyildir.
- Vaqtinchalik (Ramkalararo) Ortiqchalik: Bu ketma-ket kelgan ramkalar orasidagi ortiqchalikdir. Aksariyat videolarda sahna bir kadr dan keyingisiga to'liq o'zgarmaydi. Masalan, statik fon oldida gapirayotgan odamda katta miqdordagi vaqtinchalik ortiqchalik mavjud. Fon bir xil qoladi; faqat tasvirning kichik bir qismi (odamning yuzi va tanasi) harakatlanadi. Bu videoda siqishning eng muhim manbai hisoblanadi.
Asosiy Ramka Turlari: I-kadrlar, P-kadrlar va B-kadrlar
Vaqtinchalik ortiqchalikdan foydalanish uchun kodeklar har bir kadrni bir xil deb hisoblamaydi. Ular ularni turli turlarga tasniflaydi, bu esa Rasmlar Guruhi (GOP) deb nomlangan ketma-ketlikni hosil qiladi.
- I-kadr (Ichki kodlangan Kadr): I-kadr - bu to'liq, o'zi mustaqil tasvir. U faqat fazoviy ortiqchalik yordamida, ko'p jihatdan JPEG kabi siqiladi. I-kadrlar video oqimida langar nuqtasi bo'lib xizmat qiladi, tomoshabinga ijro etishni boshlashga yoki yangi pozitsiyaga o'tishga imkon beradi. Ular eng katta kadr turidir, lekin videoni qayta yaratish uchun muhimdir.
- P-kadr (Bashoratlangan Kadr): P-kadr oldingi I-kadr yoki P-kadr ga qarash orqali kodlanadi. Butun tasvirni saqlash o'rniga, u faqat farqlarni saqlaydi. Masalan, u "ushbu piksel blokini oxirgi kadrdan olib, uni 5 piksel o'ngga suring va mana kichik rang o'zgarishlari" kabi ko'rsatmalarni saqlaydi. Bu harakatni baholash deb nomlangan jarayon orqali amalga oshiriladi.
- B-kadr (Ikki yo'nalishli bashoratlangan Kadr): B-kadr eng samarali hisoblanadi. U bashorat qilish uchun ham oldingi, ham keyingi kadrni murojaat sifatida ishlatishi mumkin. Bu ob'ekt vaqtincha yashirinib qolib, keyin yana paydo bo'ladigan sahnalar uchun foydalidir. Oldinga va orqaga qarash orqali kodek yanada aniqroq va ma'lumotlarga samarali bashoratni yaratishi mumkin. Biroq, kelajakdagi kadr lardan foydalanish kichik kechikish (latency)ni keltirib chiqaradi, bu ularni video qo'ng'iroqlar kabi real vaqt rejimida ishlaydigan ilovalar uchun kamroq moslashtiradi.
Odatdagi GOP quyidagicha ko'rinishi mumkin: I B B P B B P B B I .... Kodlovchi siqish samaradorligi va o'tkazish qobiliyatini muvozanatlash uchun kadr larning optimal naqshini belgilaydi.
Siqish Quvuri: Bosqichma-bosqich Tahlil
Zamonaviy video kodlash ko'p bosqichli quvur liniyasidir. Har bir bosqich ma'lumotlarni siqiluvchanroq qilish uchun o'zgartiradi. Keling, bitta kadrni kodlashning asosiy bosqichlari bo'ylab yurib o'taylik.

1-bosqich: Rang Fazosi Konvertatsiyasi (RGB dan YCbCr gacha)
Aksariyat videolar RGB (Qizil, Yashil, Moviy) rang fazosida boshlanadi. Biroq, inson ko'zi yorug'lik (luma) o'zgarishlariga rang (xroma) o'zgarishlariga qaraganda ancha sezgirroq. Kodeklar buni RGB ni YCbCr kabi luma/xroma formatiga aylantirish orqali amalga oshiradi.
- Y: Luma komponenti (yorug'lik).
- Cb: Moviy farqli xroma komponenti.
- Cr: Qizil farqli xroma komponenti.
Yorug'likni rangdan ajratish orqali biz xroma past namunasini qo'llashimiz mumkin. Ushbu usul rang kanallarining (Cb va Cr) o'lchamini kamaytiradi, shu bilan birga eng sezgir bo'lgan yorug'lik kanali (Y) uchun to'liq o'lchamni saqlaydi. Umumiy sxema 4:2:0 hisoblanadi, bu sifatda deyarli sezilarli yo'qotishlarsiz rang ma'lumotlarining 75% ni tashlab yuboradi va darhol siqishga erishadi.
2-bosqich: Kadrni Partitsiyalash (Makrobloqlar)
Kodlovchi butun kadrni bir vaqtda qayta ishlamaydi. U kadrlarni makrobloqlar deb nomlangan kichikroq bloklarga, odatda 16x16 yoki 8x8 pikselga bo'ladi. Barcha keyingi qayta ishlash bosqichlari (bashoratlash, transformatsiya va boshqalar) blok-blok asosida amalga oshiriladi.
3-bosqich: Bashoratlash (Ramka ichida va Ramkalararo)
Bu sehr sodir bo'ladigan joy. Har bir makrobloq uchun kodlovchi ramka ichidagi yoki ramkalararo bashoratni ishlatishni tanlaydi.
- I-kadr (Ramka ichidagi bashorat) uchun: Kodlovchi joriy blokni shu ramka ichida joylashgan qo'shni (ustidagi va chapdagi) allaqachon kodlangan bloklarga asoslanib bashorat qiladi. Keyin u faqat bashorat va haqiqiy blok o'rtasidagi kichik farqni (qoldiqni) kodlashi kerak.
- P-kadr yoki B-kadr (Ramkalararo bashorat) uchun: Bu harakatni baholash hisoblanadi. Kodlovchi murojaat kadrida mos keladigan blokni qidiradi. Eng yaxshi moslikni topganda, u harakat vektori (masalan, "10 piksel o'ngga, 2 piksel pastga harakatlan") ni qayd qiladi va qoldiqni hisoblaydi. Ko'pincha qoldiq nolga yaqin bo'ladi, bu uni kodlash uchun juda kam bit talab qiladi.
4-bosqich: Transformatsiya (masalan, Diskret Kosinus Transformatsiyasi - DCT)
Bashoratdan so'ng, bizda qoldiq bloki bor. Ushbu blok Diskret Kosinus Transformatsiyasi (DCT) kabi matematik transformatsiyadan o'tkaziladi. DCT ma'lumotlarni o'zi siqmaydi, lekin u ularning vakilligini tubdan o'zgartiradi. U fazoviy piksel qiymatlarini chastota koeffitsientlariga aylantiradi. DCT ning ajoyibligi shundaki, aksariyat tabiiy tasvirlar uchun u vizual energiyaning ko'p qismini blokning yuqori chap burchagidagi bir nechta koeffitsientlarga (past chastotali komponentlar) to'playdi, qolgan koeffitsientlar (yuqori chastotali shovqin) esa nolga yaqin bo'ladi.
5-bosqich: Kvantizatsiya
Bu quvur liniyasidagi asosiy yo'qotishli bosqich va sifat-bit tezligi muvozanatini nazorat qilishning kalitidir. Transformatsiyalangan DCT koeffitsientlar bloki kvantizatsiya matritsasiga bo'linadi va natijalar eng yaqin butun songa yaxlitlanadi. Kvantizatsiya matritsasi yuqori chastotali koeffitsientlar uchun kattaroq qiymatlarga ega, bu ularning ko'pini nolga siqib chiqaradi. Bu erda juda ko'p ma'lumotlar tashlab yuboriladi. Yuqori kvantizatsiya parametri ko'proq nolga, yuqori siqishga va past vizual sifatga olib keladi (ko'pincha blokli artefaktlar sifatida ko'rinadi).
6-bosqich: Entropiya Kodlash
Oxirgi bosqich - bu yo'qotishsiz siqish bosqichi. Kvantizatsiyalangan koeffitsientlar, harakat vektorlari va boshqa meta-ma'lumotlar skanerlanadi va ikkilik oqimga aylantiriladi. Run-Length Encoding (RLE) va Huffman Kodlash yoki CABAC (Kontekstga moslashgan Ikkiyoqlama Aritmetik Kodlash) kabi usullar qo'llaniladi. Ushbu algormlar eng ko'p uchraydigan belgilarga (kvantizatsiya natijasida hosil bo'lgan ko'plab nollarga o'xshash) qisqa kodlarni, kamroq uchraydiganlarga esa uzoqroq kodlarni beradi, bu ma'lumotlar oqimidan so'nggi bitlarni siqib chiqaradi.
Dekoder shunchaki bu bosqichlarni teskari tartibda bajaradi: Entropiya Dekodlash -> Teskari Kvantizatsiya -> Teskari Transformatsiya -> Harakat Kompensatsiyasi -> Kadrni Qayta Tiklash.
Python'da Soddalashtirilgan Video Kodekini Amalga Oshirish
Endi, nazariyani amaliyotga tatbiq etaylik. Biz I-kadrlar va P-kadr larni ishlatadigan ta'limiy kodekni qurib chiqamiz. U asosiy quvur liniyasini namoyish etadi: Harakatni Baholash, DCT, Kvantizatsiya va tegishli dekodlash bosqichlari.
Ogohlantirish: Bu faqat o'rganish uchun mo'ljallangan o'yinchoq kodekdir. U optimallashtirilmagan va H.264 bilan solishtirish mumkin bo'lgan natijalarni bermaydi. Bizning maqsadimiz algorimlarni ishlayotganini ko'rish.
Oldingi talablar
Sizga quyidagi Python kutubxonalari kerak bo'ladi. Siz ularni pip yordamida o'rnatishingiz mumkin:
pip install numpy opencv-python scipy
Loyihaning Tuzilishi
Kodimizni bir nechta fayllarga ajratamiz:
main.py: Kodlash va dekodlash jarayonini ishga tushirish uchun asosiy skript.encoder.py: Kodlovchi mantiqini o'z ichiga oladi.decoder.py: Dekoder mantiqini o'z ichiga oladi.utils.py: Video I/U va transformatsiyalar uchun yordamchi funksiyalar.
1-qism: Asosiy Yordamchi Dasturlar (`utils.py`)
DCT, Kvantizatsiya va ularning teskarilari uchun yordamchi funksiyalar bilan boshlaymiz. Shuningdek, kadrni bloklarga bo'lish uchun ham funksiya kerak bo'ladi.
# utils.py
import numpy as np
from scipy.fftpack import dct, idct
BLOCK_SIZE = 8
# Standart JPEG kvantizatsiya matritsasi (bizning maqsadlarimiz uchun masshtablangan)
QUANTIZATION_MATRIX = 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]
])
def apply_dct(block):
"""Blokga 2D DCT qo'llaydi."""
# Piksel qiymatlarini 0 atrofida markazlashtirish
block = block - 128
return dct(dct(block.T, norm='ortho').T, norm='ortho')
def apply_idct(dct_block):
"""Blokga 2D teskari DCT qo'llaydi."""
block = idct(idct(dct_block.T, norm='ortho').T, norm='ortho')
# Markazdan chiqarish va to'g'ri piksel diapazoniga kesish
return np.round(block + 128).clip(0, 255)
def quantize(dct_block, qp=1):
"""DCT blokini kvantizatsiya qiladi. qp - bu sifat parametri."""
return np.round(dct_block / (QUANTIZATION_MATRIX * qp)).astype(int)
def dequantize(quantized_block, qp=1):
"""Blokni dekvantizatsiya qiladi."""
return quantized_block * (QUANTIZATION_MATRIX * qp)
def frame_to_blocks(frame):
"""Kadrni 8x8 bloklarga bo'ladi."""
blocks = []
h, w = frame.shape
for i in range(0, h, BLOCK_SIZE):
for j in range(0, w, BLOCK_SIZE):
blocks.append(frame[i:i+BLOCK_SIZE, j:j+BLOCK_SIZE])
return blocks
def blocks_to_frame(blocks, h, w):
"""8x8 bloklardan kadrlarni qayta tiklaydi."""
frame = np.zeros((h, w), dtype=np.uint8)
k = 0
for i in range(0, h, BLOCK_SIZE):
for j in range(0, w, BLOCK_SIZE):
frame[i:i+BLOCK_SIZE, j:j+BLOCK_SIZE] = blocks[k]
k += 1
return frame
2-qism: Kodlovchi (`encoder.py`)
Kodlovchi eng murakkab qismdir. Biz harakatni baholash uchun sodda blok-moslash algoritmini amalga oshiramiz va keyin I-kadrlar va P-kadr larni qayta ishlaymiz.
# encoder.py
import numpy as np
from utils import apply_dct, quantize, frame_to_blocks, BLOCK_SIZE
def get_motion_vectors(current_frame, reference_frame, search_range=8):
"""Harakatni baholash uchun oddiy blok-moslash algoritmi."""
h, w = current_frame.shape
motion_vectors = []
for i in range(0, h, BLOCK_SIZE):
for j in range(0, w, BLOCK_SIZE):
current_block = current_frame[i:i+BLOCK_SIZE, j:j+BLOCK_SIZE]
best_match_sad = float('inf')
best_match_vector = (0, 0)
# Murojaat kadrida qidirish
for y in range(-search_range, search_range + 1):
for x in range(-search_range, search_range + 1):
ref_i, ref_j = i + y, j + x
if 0 <= ref_i <= h - BLOCK_SIZE and 0 <= ref_j <= w - BLOCK_SIZE:
ref_block = reference_frame[ref_i:ref_i+BLOCK_SIZE, ref_j:ref_j+BLOCK_SIZE]
sad = np.sum(np.abs(current_block - ref_block))
if sad < best_match_sad:
best_match_sad = sad
best_match_vector = (y, x)
motion_vectors.append(best_match_vector)
return motion_vectors
def encode_iframe(frame, qp=1):
"""I-kadrni kodlaydi."""
h, w = frame.shape
blocks = frame_to_blocks(frame)
quantized_blocks = []
for block in blocks:
dct_block = apply_dct(block.astype(float))
quantized_block = quantize(dct_block, qp)
quantized_blocks.append(quantized_block)
return {'type': 'I', 'h': h, 'w': w, 'data': quantized_blocks, 'qp': qp}
def encode_pframe(current_frame, reference_frame, qp=1):
"""P-kadrni kodlaydi."""
h, w = current_frame.shape
motion_vectors = get_motion_vectors(current_frame, reference_frame)
quantized_residuals = []
k = 0
for i in range(0, h, BLOCK_SIZE):
for j in range(0, w, BLOCK_SIZE):
current_block = current_frame[i:i+BLOCK_SIZE, j:j+BLOCK_SIZE]
mv_y, mv_x = motion_vectors[k]
ref_block = reference_frame[i+mv_y : i+mv_y+BLOCK_SIZE, j+mv_x : j+mv_x+BLOCK_SIZE]
residual = current_block.astype(float) - ref_block.astype(float)
dct_residual = apply_dct(residual)
quantized_residual = quantize(dct_residual, qp)
quantized_residuals.append(quantized_residual)
k += 1
return {'type': 'P', 'motion_vectors': motion_vectors, 'data': quantized_residuals, 'qp': qp}
3-qism: Dekoder (`decoder.py`)
Dekoder jarayonni teskarisiga bajaradi. P-kadr lar uchun u saqlangan harakat vektorlaridan foydalanib harakat kompensatsiyasini amalga oshiradi.
# decoder.py
import numpy as np
from utils import apply_idct, dequantize, blocks_to_frame, BLOCK_SIZE
def decode_iframe(encoded_frame):
"""I-kadrni dekodlaydi."""
h, w = encoded_frame['h'], encoded_frame['w']
qp = encoded_frame['qp']
quantized_blocks = encoded_frame['data']
reconstructed_blocks = []
for q_block in quantized_blocks:
dct_block = dequantize(q_block, qp)
block = apply_idct(dct_block)
reconstructed_blocks.append(block.astype(np.uint8))
return blocks_to_frame(reconstructed_blocks, h, w)
def decode_pframe(encoded_frame, reference_frame):
"""O'zining murojaat kadridan foydalanib P-kadrni dekodlaydi."""
h, w = reference_frame.shape
qp = encoded_frame['qp']
motion_vectors = encoded_frame['motion_vectors']
quantized_residuals = encoded_frame['data']
reconstructed_blocks = []
k = 0
for i in range(0, h, BLOCK_SIZE):
for j in range(0, w, BLOCK_SIZE):
# Qoldiqni dekodlash
dct_residual = dequantize(quantized_residuals[k], qp)
residual = apply_idct(dct_residual)
# Harakat kompensatsiyasini amalga oshirish
mv_y, mv_x = motion_vectors[k]
ref_block = reference_frame[i+mv_y : i+mv_y+BLOCK_SIZE, j+mv_x : j+mv_x+BLOCK_SIZE]
# Bloki qayta tiklash
reconstructed_block = (ref_block.astype(float) + residual).clip(0, 255)
reconstructed_blocks.append(reconstructed_block.astype(np.uint8))
k += 1
return blocks_to_frame(reconstructed_blocks, h, w)
4-qism: Hammasini Bir Joyga Qo'yish (`main.py`)
Ushbu skript butun jarayonni boshqaradi: videoni o'qish, uni kadrma-kadr kodlash va keyin yakuniy natijani yaratish uchun dekodlash.
# main.py
import cv2
import pickle # Bizning siqilgan ma'lumotlar strukturasini saqlash/yuklash uchun
from encoder import encode_iframe, encode_pframe
from decoder import decode_iframe, decode_pframe
def main(input_path, output_path, compressed_file_path):
cap = cv2.VideoCapture(input_path)
frames = []
while True:
ret, frame = cap.read()
if not ret:
break
# Oddiylik uchun kulrang (luma) kanal bilan ishlaymiz
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY))
cap.release()
# --- KODLASH --- #
print("Kodlanmoqda...")
compressed_data = []
reference_frame = None
gop_size = 12 # Har 12 kadrdan keyin I-kadr
for i, frame in enumerate(frames):
if i % gop_size == 0:
# I-kadr sifatida kodlash
encoded_frame = encode_iframe(frame, qp=2.5)
compressed_data.append(encoded_frame)
print(f"Kadr {i} I-kadr sifatida kodlandi")
else:
# P-kadr sifatida kodlash
encoded_frame = encode_pframe(frame, reference_frame, qp=2.5)
compressed_data.append(encoded_frame)
print(f"Kadr {i} P-kadr sifatida kodlandi")
# Keyingi P-kadr uchun murojaat oxirgi qayta tiklangan kadr bo'lishi kerak
if encoded_frame['type'] == 'I':
reference_frame = decode_iframe(encoded_frame)
else:
reference_frame = decode_pframe(encoded_frame, reference_frame)
with open(compressed_file_path, 'wb') as f:
pickle.dump(compressed_data, f)
print(f"Siqilgan ma'lumotlar {compressed_file_path} ga saqlandi")
# --- DEKODLASH --- #
print("\nDekodlanmoqda...")
with open(compressed_file_path, 'rb') as f:
loaded_compressed_data = pickle.load(f)
decoded_frames = []
reference_frame = None
for i, encoded_frame in enumerate(loaded_compressed_data):
if encoded_frame['type'] == 'I':
decoded_frame = decode_iframe(encoded_frame)
print(f"Kadr {i} (I-kadr) dekodlandi")
else:
decoded_frame = decode_pframe(encoded_frame, reference_frame)
print(f"Kadr {i} (P-kadr) dekodlandi")
decoded_frames.append(decoded_frame)
reference_frame = decoded_frame
# --- NATIJAVIY VIDEONI YOZISH --- #
h, w = decoded_frames[0].shape
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, 30.0, (w, h), isColor=False)
for frame in decoded_frames:
out.write(frame)
out.release()
print(f"Dekodlangan video {output_path} ga saqlandi")
if __name__ == '__main__':
main('input.mp4', 'output.mp4', 'compressed.bin')
Natijalarni Tahlil Qilish va Keyingi Tadqiqotlar
main.py skriptini input.mp4 fayli bilan ishga tushirgandan so'ng, siz ikkita fayl olasiz: compressed.bin, unda bizning maxsus siqilgan video ma'lumotlarimiz mavjud, va output.mp4, qayta tiklangan video. Siqish darajasini ko'rish uchun input.mp4 hajmini compressed.bin bilan solishtiring. Sifatni ko'rish uchun output.mp4 ni vizual tekshiring. Yuqori `qp` qiymati bilan, bu odatda kvantizatsiyaning klassik belgisi bo'lgan blokli artefaktlarni ko'rishingiz mumkin.
Sifatni O'lchash: Eng Yuqori Signal-Shovqin Nisbati (PSNR)
Qayta tiklash sifatini o'lchash uchun keng tarqalgan ob'ektiv metrika PSNR hisoblanadi. U asl kadrni dekodlangan kadr bilan solishtiradi. Yuqori PSNR odatda yaxshiroq sifatni ko'rsatadi.
import numpy as np
import math
def calculate_psnr(original, compressed):
mse = np.mean((original - compressed) ** 2)
if mse == 0:
return float('inf')
max_pixel = 255.0
psnr = 20 * math.log10(max_pixel / math.sqrt(mse))
return psnr
Cheklovlar va Keyingi Qadamlar
Bizning oddiy kodekimiz - bu ajoyib boshlanish, lekin u mukammallikdan yiroq. Mana ba'zi cheklovlar va potentsial yaxshilanishlar, ular haqiqiy kodeklarning rivojlanishini aks ettiradi:
- Harakatni Baholash: Bizning keng qamrovli qidiruvimiz sekin va oddiy. Haqiqiy kodeklar harakat vektorlarini ancha tezroq topish uchun murakkab, ierarxik qidiruv algorimlardan foydalanadi.
- B-kadr lar: Biz faqat P-kadr larni amalga oshirdik. B-kadr larni qo'shish murakkablik va kechikishni oshirish evaziga siqish samaradorligini sezilarli darajada oshiradi.
- Entropiya Kodlash: Biz to'g'ri entropiya kodlash bosqichini amalga oshirmadik. Biz shunchaki Python ma'lumotlar tuzilmalarini picklade qildik. Kvantizatsiyalangan nollar uchun Run-Length Encoder, so'ngra Huffman yoki Aritmetik kodlovchini qo'shish fayl hajmini yanada kamaytiradi.
- Bloklashdan Tozalash filtri: Bizning 8x8 bloklarimiz orasidagi aniq qirralar ko'rinadigan artefaktlarga olib keladi. Zamonaviy kodeklar vizual sifatni yaxshilash uchun ushbu qirralarni tekislash uchun qayta tiklashdan so'ng deblocking filtrini qo'llaydi.
- O'zgaruvchan Blok Hajmlari: Zamonaviy kodeklar shunchaki aniqlangan 16x16 makrobloqlardan foydalanmaydi. Ular kontentga yaxshiroq mos kelishi uchun kadrlarni turli blok hajmlari va shakllariga mos ravishda partitsiyalashlari mumkin (masalan, tekis hududlar uchun kattaroq bloklar va batafsil hududlar uchun kichikroq bloklardan foydalanish).
Xulosa
Video kodekini yaratish, hatto soddalashtirilganini ham, chuqur mukofot beruvchi mashqdir. U bizning raqamli hayotimizning muhim qismini tashkil etadigan texnologiyani sirli qilib ochadi. Biz fazoviy va vaqtinchalik ortiqchalikning asosiy tushunchalari bo'ylab sayohat qildik, kodlash quvurining muhim bosqichlari - bashoratlash, transformatsiya va kvantizatsiya - bo'ylab yurib o'tdik va ushbu g'oyalarni Python'da amalga oshirdik.
Bu yerda keltirilgan kod - bu boshlang'ich nuqta. Sizni u bilan tajriba o'tkazishga undayman. Blok hajmini, kvantizatsiya parametrini (`qp`) yoki GOP uzunligini o'zgartirishga harakat qiling. Oddiy Run-Length Encoding sxemasini amalga oshirishga urinib ko'ring yoki hatto B-kadr larni qo'shish qiyinchiligini yengib chiqing. Qurish va buzish orqali siz ko'pincha tabiiy deb qabul qiladigan muammosiz video tajribalar ortidagi zukkolikni chuqur tushunishga erishasiz. Video siqish dunyosi keng va doimo rivojlanib bormoqda, bu o'rganish va innovatsiyalar uchun cheksiz imkoniyatlar yaratadi.