பைத்தானைப் பயன்படுத்தி, வீடியோ சுருக்க வழிமுறைகளைப் பற்றி புரிந்துகொள்வதற்கும் செயல்படுத்துவதற்கும் ஒரு விரிவான வழிகாட்டி. நவீன வீடியோ கோடெக்குகளின் கோட்பாடு மற்றும் நடைமுறையைப் பற்றி அறிக.
பைத்தானில் வீடியோ கோடெக்கை உருவாக்குதல்: சுருக்க வழிமுறைகளில் ஆழ்ந்த ஆய்வு
எங்கள் ஹைப்பர்-இணைக்கப்பட்ட உலகில், வீடியோதான் ராஜா. ஸ்ட்ரீமிங் சேவைகள் மற்றும் வீடியோ கான்பரன்சிங் முதல் சமூக ஊடக ஊட்டங்கள் வரை, டிஜிட்டல் வீடியோ இணைய போக்குவரத்தை ஆதிக்கம் செலுத்துகிறது. ஆனால், நிலையான இணைய இணைப்பில் ஹை-டெபினிஷன் திரைப்படத்தை அனுப்புவது எப்படி சாத்தியமாகும்? இதற்கு விடை ஒரு அற்புதமான மற்றும் சிக்கலான துறையில் உள்ளது: வீடியோ சுருக்கம். இந்த தொழில்நுட்பத்தின் மையத்தில் வீடியோ கோடெக் (COder-DECoder) உள்ளது, இது ஒரு அதிநவீன வழிமுறைகளின் தொகுப்பாகும், இது காட்சி தரத்தைப் பாதுகாக்கும்போது கோப்பு அளவை பெரிதும் குறைக்கும் வகையில் வடிவமைக்கப்பட்டுள்ளது.
H.264, HEVC (H.265) மற்றும் ராயல்டி இல்லாத AV1 போன்ற தொழில்-நிலையான கோடெக்குகள் நம்பமுடியாத அளவிற்கு சிக்கலான பொறியியல் துண்டுகளாக இருந்தாலும், அவற்றின் அடிப்படைக் கொள்கைகளைப் புரிந்துகொள்வது எந்தவொரு ஆர்வமுள்ள டெவலப்பருக்கும் அணுகக்கூடியது. இந்த வழிகாட்டி உங்களை வீடியோ சுருக்க உலகில் ஆழமாக அழைத்துச் செல்லும். நாங்கள் கோட்பாட்டைப் பற்றி மட்டும் பேச மாட்டோம்; பைத்தானைப் பயன்படுத்தி பூஜ்ஜியத்திலிருந்து ஒரு எளிமைப்படுத்தப்பட்ட, கல்வி வீடியோ கோடெக்கை உருவாக்குவோம். இந்த நடைமுறை அணுகுமுறை நவீன வீடியோ ஸ்ட்ரீமிங்கை சாத்தியமாக்கும் நேர்த்தியான யோசனைகளைப் புரிந்துகொள்வதற்கான சிறந்த வழியாகும்.
ஏன் பைத்தான்? உண்மையான நேரத்தில், அதிக செயல்திறன் கொண்ட வணிக ரீதியான கோடெக்கிற்கு (இது பொதுவாக C/C++ அல்லது அசெம்பிளியில் எழுதப்படும்) நீங்கள் பயன்படுத்தும் மொழியாக இல்லாவிட்டாலும், பைத்தானின் படிக்கக்கூடிய தன்மை மற்றும் NumPy, SciPy மற்றும் OpenCV போன்ற அதன் சக்திவாய்ந்த நூலகங்கள் கற்றல், முன்மாதிரி மற்றும் ஆராய்ச்சிக்கு சரியான சூழலை உருவாக்குகின்றன. குறைந்த-நிலை நினைவக மேலாண்மையில் சிக்கிக்கொள்ளாமல் வழிமுறைகளில் கவனம் செலுத்தலாம்.
வீடியோ சுருக்கத்தின் முக்கிய கருத்துகளைப் புரிந்துகொள்வது
ஒரு வரி குறியீட்டை எழுதுவதற்கு முன், நாம் என்ன அடைய முயற்சிக்கிறோம் என்பதைப் புரிந்து கொள்ள வேண்டும். வீடியோ சுருக்கத்தின் நோக்கம் தேவையற்ற தரவை நீக்குவதாகும். ஒரு மூல, சுருக்கப்படாத வீடியோ மிகப்பெரியது. ஒரு நிமிட 1080p வீடியோ 30 பிரேம்கள் ஒரு நொடிக்கு 7 GB க்கு மேல் இருக்கலாம். இந்த தரவு மிருகத்தை அடக்குவதற்கு, இரண்டு முதன்மை வகையான மிதமிஞ்சிய தன்மையைப் பயன்படுத்துகிறோம்.
சுருக்கத்தின் இரண்டு தூண்கள்: ஸ்பேஷியல் மற்றும் டெம்போரல் மிதமிஞ்சிய தன்மை
- ஸ்பேஷியல் (உள்-சட்டகம்) மிதமிஞ்சிய தன்மை: இது ஒரு சட்டகத்திற்குள் மிதமிஞ்சிய தன்மை. பெரிய நீல வானம் அல்லது வெள்ளை சுவர் பற்றி சிந்தியுங்கள். அந்த பகுதியில் உள்ள ஒவ்வொரு பிக்சலுக்கும் வண்ண மதிப்பை சேமிப்பதற்குப் பதிலாக, அதை மிகவும் திறமையாக விவரிக்க முடியும். இது JPEG போன்ற பட சுருக்க வடிவங்களுக்குப் பின்னால் உள்ள அதே கொள்கையாகும்.
- டெம்போரல் (இன்டர்-பிரேம்) மிதமிஞ்சிய தன்மை: இது அடுத்தடுத்த பிரேம்களுக்கு இடையே உள்ள மிதமிஞ்சிய தன்மை. பெரும்பாலான வீடியோக்களில், காட்சி ஒன்று முதல் அடுத்த பிரேம் வரை முழுமையாக மாறாது. நிலையான பின்னணிக்கு எதிராகப் பேசும் ஒரு நபர், எடுத்துக்காட்டாக, மிகப்பெரிய அளவிலான டெம்போரல் மிதமிஞ்சிய தன்மையைக் கொண்டிருக்கிறார்கள். பின்னணி அப்படியே உள்ளது; படத்தின் ஒரு சிறிய பகுதி (நபரின் முகம் மற்றும் உடல்) மட்டுமே நகரும். இது வீடியோவில் சுருக்கத்தின் மிக முக்கியமான ஆதாரமாகும்.
முக்கிய சட்டக வகைகள்: I-பிரேம்கள், P-பிரேம்கள் மற்றும் B-பிரேம்கள்
டெம்போரல் மிதமிஞ்சிய தன்மையைப் பயன்படுத்த, கோடெக்குகள் ஒவ்வொரு பிரேமையும் சமமாக நடத்தாது. அவை அவற்றை வெவ்வேறு வகைகளாக வகைப்படுத்துகின்றன, இது படங்களின் குழுவை (GOP) உருவாக்குகிறது.
- I-பிரேம் (உள்-குறியிடப்பட்ட பிரேம்): I-பிரேம் என்பது ஒரு முழுமையான, சுய-கட்டுப்படுத்தப்பட்ட படம். இது JPEG போல, ஸ்பேஷியல் மிதமிஞ்சிய தன்மையைப் பயன்படுத்தி சுருக்கப்படுகிறது. I-பிரேம்கள் வீடியோ ஸ்ட்ரீமில் ஆங்கர் புள்ளிகளாக செயல்படுகின்றன, பார்வையாளரை பிளேபேக்கைத் தொடங்க அல்லது புதிய நிலைக்குச் செல்ல அனுமதிக்கிறது. அவை மிகப்பெரிய சட்ட வகை, ஆனால் வீடியோவை மீண்டும் உருவாக்க அவசியமானவை.
- P-பிரேம் (முன்னறிவிக்கப்பட்ட பிரேம்): P-பிரேம் முந்தைய I-பிரேம் அல்லது P-பிரேமைப் பார்த்து குறியிடப்படுகிறது. முழு படத்தையும் சேமிப்பதற்குப் பதிலாக, அது வேறுபாடுகளை மட்டுமே சேமிக்கிறது. எடுத்துக்காட்டாக, “கடைசி சட்டகத்திலிருந்து இந்த பிக்சல்களின் தொகுப்பை எடுத்து, அதை 5 பிக்சல்களை வலப்புறம் நகர்த்தவும், மற்றும் சிறிய வண்ண மாற்றங்கள் இங்கே” போன்ற வழிமுறைகளைச் சேமிக்கிறது. இது இயக்க மதிப்பீடு எனப்படும் ஒரு செயல்முறை மூலம் அடையப்படுகிறது.
- B-பிரேம் (இரு திசையிலும் முன்னறிவிக்கப்பட்ட பிரேம்): B-பிரேம் மிகவும் திறமையானது. முன்னறிவிப்புக்காக முந்தைய மற்றும் அடுத்த பிரேம் இரண்டையும் குறிப்புகளாகப் பயன்படுத்தலாம். ஒரு பொருள் தற்காலிகமாக மறைந்து மீண்டும் தோன்றும் காட்சிகளுக்கு இது பயனுள்ளதாக இருக்கும். முன்னோக்கி மற்றும் பின்னோக்கிப் பார்ப்பதன் மூலம், கோடெக் மிகவும் துல்லியமான மற்றும் தரவு-திறனுள்ள முன்னறிவிப்பை உருவாக்க முடியும். இருப்பினும், எதிர்கால பிரேம்களைப் பயன்படுத்துவது ஒரு சிறிய தாமதத்தை (லேட்டன்சி) அறிமுகப்படுத்துகிறது, இது வீடியோ அழைப்புகள் போன்ற நிகழ்நேர பயன்பாடுகளுக்கு குறைவாகவே பொருத்தமானது.
ஒரு வழக்கமான GOP இப்படி இருக்கலாம்: I B B P B B P B B I .... சுருக்க திறன் மற்றும் தேடலுக்கான சமநிலையைத் தக்கவைக்க, பிரேம்களின் உகந்த முறையை என்கோடர் தீர்மானிக்கிறது.
சுருக்கப் பாதை: படிப்படியான முறிவு
நவீன வீடியோ குறியீட்டு என்பது பல-நிலை பைப்லைனாகும். ஒவ்வொரு கட்டமும் தரவை மாற்றியமைக்கிறது, அதை மேலும் சுருக்கக்கூடியதாக மாற்றுகிறது. ஒரு சட்டகத்தை குறியிடுவதற்கான முக்கிய படிகளைப் பார்ப்போம்.

படி 1: வண்ண ஸ்பேஸ் மாற்றம் (RGB முதல் YCbCr)
பெரும்பாலான வீடியோ RGB (சிவப்பு, பச்சை, நீலம்) வண்ண இடத்தில் தொடங்குகிறது. இருப்பினும், மனித கண் பிரகாசத்தில் (லுமா) ஏற்படும் மாற்றங்களுக்கு மிகவும் உணர்திறன் கொண்டது, இது வண்ணத்தில் (குரோமா) ஏற்படும் மாற்றங்களை விட அதிகம். கோடெக்குகள் RGB ஐ YCbCr போன்ற லுமா/குரோமா வடிவத்திற்கு மாற்றுவதன் மூலம் இதைப் பயன்படுத்துகின்றன.
- Y: லுமா கூறு (பிரகாசம்).
- Cb: நீல-வேறுபாடு குரோமா கூறு.
- Cr: சிவப்பு-வேறுபாடு குரோமா கூறு.
பிரகாசத்தை வண்ணத்திலிருந்து பிரிப்பதன் மூலம், குரோமா துணை மாதிரியைக்கொள்ள முடியும். இந்த நுட்பம் வண்ண சேனல்களின் (Cb மற்றும் Cr) தெளிவுத்திறனைக் குறைக்கிறது, பிரகாச சேனலுக்கான முழு தெளிவுத்திறனை (Y) வைத்திருக்கிறது, இதற்கு நம் கண்கள் மிகவும் உணர்திறன் கொண்டவை. ஒரு பொதுவான திட்டம் 4:2:0 ஆகும், இது தரத்தில் கிட்டத்தட்ட புலப்படாத இழப்புடன் வண்ண தகவலின் 75% ஐ நிராகரிக்கிறது, உடனடியாக சுருக்கத்தை அடைய முடிகிறது.
படி 2: சட்டக பகிர்வு (மேக்ரோப்ளாக்குகள்)
குறியீட்டாளர் முழு பிரேமையும் ஒரே நேரத்தில் செயலாக்க மாட்டார். இது பிரேமை சிறிய தொகுதிகளாகப் பிரிக்கிறது, பொதுவாக 16x16 அல்லது 8x8 பிக்சல்கள், இது மேக்ரோப்ளாக்குகள் என்று அழைக்கப்படுகிறது. அனைத்து அடுத்தடுத்த செயலாக்க படிகளும் (முன்னறிவிப்பு, மாற்றம், முதலியன) தொகுதிக்கு தொகுதி அடிப்படையில் செய்யப்படுகின்றன.
படி 3: முன்னறிவிப்பு (இன்டர் மற்றும் இன்ட்ரா)
இங்குதான் மேஜிக் நடக்கிறது. ஒவ்வொரு மேக்ரோப்ளாக்கிற்கும், குறியீட்டாளர் இன்ட்ரா-பிரேம் அல்லது இன்டர்-பிரேம் முன்னறிவிப்பைப் பயன்படுத்த வேண்டுமா என்பதை முடிவு செய்கிறார்.
- ஒரு I-பிரேமிற்கு (இன்ட்ரா-முன்னறிவிப்பு): குறியீட்டாளர் தற்போதைய தொகுதியை அதே சட்டகத்திற்குள் ஏற்கனவே குறியிடப்பட்ட அண்டை வீட்டார்களின் (மேலே மற்றும் இடதுபுறத்தில் உள்ள தொகுதிகள்) பிக்சல்களைப் பொறுத்து முன்னறிவிக்கிறார். பின்னர், முன்னறிவிப்புக்கும், உண்மையான தொகுதிக்கும் இடையிலான சிறிய வித்தியாசத்தை (மீதமுள்ளவை) குறியிட வேண்டும்.
- ஒரு P-பிரேம் அல்லது B-பிரேமிற்கு (இன்டர்-முன்னறிவிப்பு): இது இயக்க மதிப்பீடு ஆகும். குறியீட்டாளர் ஒரு குறிப்பு சட்டகத்தில் ஒரு பொருந்தக்கூடிய தொகுதியைத் தேடுகிறார். சிறந்த பொருத்தத்தைக் கண்டறிந்ததும், அது ஒரு இயக்க திசையனைப் பதிவு செய்கிறது (எ.கா., “10 பிக்சல்கள் வலதுபுறமும், 2 பிக்சல்கள் கீழேயும் நகர்த்தவும்”) மற்றும் மீதமுள்ளவற்றைக் கணக்கிடுகிறது. அடிக்கடி, மீதமுள்ளவை பூஜ்ஜியத்திற்கு அருகில் இருக்கும், குறியிட சில பிட்களை மட்டுமே தேவைப்படும்.
படி 4: மாற்றம் (எ.கா., டிஸ்க்ரீட் கோசைன் டிரான்ஸ்ஃபார்ம் - DCT)
முன்னறிவித்தலுக்குப் பிறகு, நமக்கு ஒரு மீதமுள்ள தொகுதி உள்ளது. இந்த தொகுதி டிஸ்க்ரீட் கோசைன் டிரான்ஸ்ஃபார்ம் (DCT) போன்ற ஒரு கணித மாற்றத்தின் மூலம் இயக்கப்படுகிறது. DCT தரவை சுருக்காது, ஆனால் அது எவ்வாறு பிரதிநிதித்துவப்படுத்தப்படுகிறது என்பதை அடிப்படையாக மாற்றுகிறது. இது ஸ்பேஷியல் பிக்சல் மதிப்புகளை அதிர்வெண் குணகங்களாக மாற்றுகிறது. DCT யின் மேஜிக் என்னவென்றால், பெரும்பாலான இயற்கை படங்களுக்கு, அது பெரும்பாலான காட்சி ஆற்றலை தொகுதியின் மேல்-இடது மூலையில் உள்ள சில குணகங்களில் (குறைந்த அதிர்வெண் கூறுகள்) செலுத்துகிறது, மீதமுள்ள குணகங்கள் (அதிக அதிர்வெண் சத்தம்) பூஜ்ஜியத்திற்கு அருகில் இருக்கும்.
படி 5: குவாண்டிசேஷன்
இது பைப்லைனில் உள்ள முதன்மை இழப்பு நிலை மற்றும் தரம்-விஎஸ்-பிட்ரேட் வர்த்தகத்தை கட்டுப்படுத்துவதற்கான திறவுகோலாகும். மாற்றப்பட்ட DCT குணகங்களின் தொகுதி ஒரு குவாண்டிசேஷன் அணியால் வகுக்கப்படுகிறது, மேலும் முடிவுகள் நெருக்கமான முழு எண்ணுக்கு வட்டமிடப்படுகின்றன. குவாண்டிசேஷன் அணி அதிக அதிர்வெண் குணகங்களுக்கு பெரிய மதிப்புகளைக் கொண்டுள்ளது, இவை பலவற்றை பூஜ்ஜியமாக மாற்றுகிறது. இங்குதான் அதிக அளவு தரவு நிராகரிக்கப்படுகிறது. அதிக குவாண்டிசேஷன் அளவுருக்கள் அதிக பூஜ்ஜியங்களுக்கும், அதிக சுருக்கத்திற்கும் மற்றும் குறைந்த காட்சி தரத்திற்கும் வழிவகுக்கும் (பெரும்பாலும் பிளாக்கி ஆர்டிஃபேக்டுகளாகக் காணப்படுகிறது).
படி 6: என்ட்ரோபி கோடிங்
இறுதி நிலை ஒரு இழப்பு இல்லாத சுருக்க படியாகும். குவாண்டிஸ் செய்யப்பட்ட குணகங்கள், இயக்க திசையன்கள் மற்றும் பிற மெட்டாடேட்டாக்கள் ஸ்கேன் செய்யப்பட்டு ஒரு பைனரி ஸ்ட்ரீமாக மாற்றப்படுகின்றன. ரன்-லென்த் என்கோடிங் (RLE) மற்றும் ஹஃப்மேன் கோடிங் அல்லது CABAC (சூழல்-தழுவிய பைனரி அரித்மெடிக் கோடிங்) போன்ற மேம்பட்ட முறைகள் பயன்படுத்தப்படுகின்றன. இந்த வழிமுறைகள் அடிக்கடி நிகழும் சின்னங்களுக்கு (குவாண்டிசேஷனால் உருவாக்கப்பட்ட பல பூஜ்ஜியங்கள் போன்றவை) சிறிய குறியீடுகளையும், குறைவாக நிகழும் சின்னங்களுக்கு நீண்ட குறியீடுகளையும் ஒதுக்குகின்றன, தரவு ஸ்ட்ரீமில் இருந்து இறுதி பிட்களைப் பிழிந்து எடுக்கின்றன.
டிகோடர் இந்த படிகளை தலைகீழாகச் செய்கிறது: என்ட்ரோபி டிகோடிங் -> தலைகீழ் குவாண்டிசேஷன் -> தலைகீழ் மாற்றம் -> இயக்க இழப்பீடு -> சட்டகத்தை மறுசீரமைத்தல்.
பைத்தானில் எளிமைப்படுத்தப்பட்ட வீடியோ கோடெக்கை செயல்படுத்துதல்
இப்போது, கோட்பாட்டை நடைமுறைக்குக் கொண்டு வருவோம். I-பிரேம்கள் மற்றும் P-பிரேம்களைப் பயன்படுத்தும் ஒரு கல்வி கோடெக்கை உருவாக்குவோம். இது முக்கிய பைப்லைனை நிரூபிக்கும்: இயக்க மதிப்பீடு, DCT, குவாண்டிசேஷன் மற்றும் தொடர்புடைய டிகோடிங் படிகள்.
மறுப்பு: இது கற்றலுக்காக வடிவமைக்கப்பட்ட ஒரு *பொம்மை* கோடெக் ஆகும். இது உகந்ததாக இல்லை மற்றும் H.264 க்கு இணையாக முடிவுகளை உருவாக்காது. வழிமுறைகளை செயல்பாட்டில் பார்ப்பதே எங்கள் குறிக்கோள்.
முன்தேவைகள்
உங்களுக்கு பின்வரும் பைத்தான் நூலகங்கள் தேவைப்படும். நீங்கள் இவற்றை pip பயன்படுத்தி நிறுவலாம்:
pip install numpy opencv-python scipy
திட்ட அமைப்பு
எங்கள் குறியீட்டை சில கோப்புகளாக ஒழுங்கமைப்போம்:
main.py: குறியீட்டு மற்றும் டிகோடிங் செயல்முறையை இயக்க முக்கிய ஸ்கிரிப்ட்.encoder.py: குறியீட்டாளருக்கான தர்க்கத்தைக் கொண்டுள்ளது.decoder.py: டிகோடிங்க்கான தர்க்கத்தைக் கொண்டுள்ளது.utils.py: வீடியோ I/O மற்றும் மாற்றங்களுக்கான ஹெல்பர் செயல்பாடுகள்.
பகுதி 1: முக்கிய பயன்பாடுகள் (`utils.py`)
DCT, குவாண்டிசேஷன் மற்றும் அவற்றின் தலைகீழிகளுக்கான ஹெல்பர் செயல்பாடுகளுடன் தொடங்குவோம். ஒரு சட்டகத்தை தொகுதிகளாகப் பிரிக்க ஒரு செயல்பாடும் எங்களுக்குத் தேவைப்படும்.
# utils.py
import numpy as np
from scipy.fftpack import dct, idct
BLOCK_SIZE = 8
# A standard JPEG quantization matrix (scaled for our purposes)
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):
"""Applies 2D DCT to a block."""
# Center the pixel values around 0
block = block - 128
return dct(dct(block.T, norm='ortho').T, norm='ortho')
def apply_idct(dct_block):
"""Applies 2D Inverse DCT to a block."""
block = idct(idct(dct_block.T, norm='ortho').T, norm='ortho')
# De-center and clip to valid pixel range
return np.round(block + 128).clip(0, 255)
def quantize(dct_block, qp=1):
"""Quantizes a DCT block. qp is a quality parameter."""
return np.round(dct_block / (QUANTIZATION_MATRIX * qp)).astype(int)
def dequantize(quantized_block, qp=1):
"""Dequantizes a block."""
return quantized_block * (QUANTIZATION_MATRIX * qp)
def frame_to_blocks(frame):
"""Splits a frame into 8x8 blocks."""
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):
"""Reconstructs a frame from 8x8 blocks."""
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: குறியீட்டாளர் (`encoder.py`)
குறியீட்டாளர் மிகவும் சிக்கலான பகுதி. இயக்க மதிப்பீட்டிற்காக ஒரு எளிய தொகுதி-பொருத்த வழிமுறையை செயல்படுத்துவோம், பின்னர் I-பிரேம்கள் மற்றும் P-பிரேம்களை செயலாக்குவோம்.
# 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):
"""A simple block matching algorithm for motion estimation."""
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)
# Search in the reference frame
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):
"""Encodes an I-frame."""
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):
"""Encodes a P-frame."""
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: டிகோடர் (`decoder.py`)
டிகோடர் செயல்முறையை தலைகீழாக மாற்றுகிறது. P-பிரேம்களுக்கு, அது சேமிக்கப்பட்ட இயக்க திசையன்களைப் பயன்படுத்தி இயக்க இழப்பீட்டைச் செய்கிறது.
# decoder.py
import numpy as np
from utils import apply_idct, dequantize, blocks_to_frame, BLOCK_SIZE
def decode_iframe(encoded_frame):
"""Decodes an I-frame."""
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):
"""Decodes a P-frame using its reference frame."""
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):
# Decode the residual
dct_residual = dequantize(quantized_residuals[k], qp)
residual = apply_idct(dct_residual)
# Perform motion compensation
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]
# Reconstruct the block
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: அனைத்தையும் ஒன்றாக இணைத்தல் (`main.py`)
இந்த ஸ்கிரிப்ட் முழு செயல்முறையையும் ஒருங்கிணைக்கிறது: ஒரு வீடியோவைப் படித்து, அதை பிரேம் பை பிரேம் குறியிடுவது, பின்னர் இறுதி வெளியீட்டை உருவாக்க டிகோட் செய்வது.
# main.py
import cv2
import pickle # For saving/loading our compressed data structure
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
# We'll work with the grayscale (luma) channel for simplicity
frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY))
cap.release()
# --- ENCODING --- #
print("Encoding...")
compressed_data = []
reference_frame = None
gop_size = 12 # I-frame every 12 frames
for i, frame in enumerate(frames):
if i % gop_size == 0:
# Encode as I-frame
encoded_frame = encode_iframe(frame, qp=2.5)
compressed_data.append(encoded_frame)
print(f"Encoded frame {i} as I-frame")
else:
# Encode as P-frame
encoded_frame = encode_pframe(frame, reference_frame, qp=2.5)
compressed_data.append(encoded_frame)
print(f"Encoded frame {i} as P-frame")
# The reference for the next P-frame needs to be the *reconstructed* last frame
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"Compressed data saved to {compressed_file_path}")
# --- DECODING --- #
print("\nDecoding...")
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"Decoded frame {i} (I-frame)")
else:
decoded_frame = decode_pframe(encoded_frame, reference_frame)
print(f"Decoded frame {i} (P-frame)")
decoded_frames.append(decoded_frame)
reference_frame = decoded_frame
# --- WRITING OUTPUT VIDEO --- #
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"Decoded video saved to {output_path}")
if __name__ == '__main__':
main('input.mp4', 'output.mp4', 'compressed.bin')
முடிவுகளை பகுப்பாய்வு செய்தல் மற்றும் மேலும் ஆராய்தல்
`input.mp4` கோப்புடன் `main.py` ஸ்கிரிப்டை இயக்கிய பிறகு, உங்களுக்கு இரண்டு கோப்புகள் கிடைக்கும்: `compressed.bin`, இதில் எங்கள் விருப்ப சுருக்கப்பட்ட வீடியோ தரவு உள்ளது, மற்றும் `output.mp4`, மறுசீரமைக்கப்பட்ட வீடியோ. சுருக்க விகிதத்தை காண `input.mp4` இன் அளவை `compressed.bin` உடன் ஒப்பிடுக. தரத்தைப் பார்க்க `output.mp4` ஐப் பார்க்கவும். நீங்கள் பிளாக்கி ஆர்டிஃபேக்டுகளைக் காண்பீர்கள், குறிப்பாக `qp` மதிப்பை அதிகமாகக் கொண்டால், இது குவாண்டிசேஷனின் ஒரு உன்னதமான அறிகுறியாகும்.
தரம் அளவிடுதல்: உச்ச சிக்னல்-டு-நாய்ஸ் ரேஷியோ (PSNR)
மறுசீரமைப்பின் தரத்தை அளவிடுவதற்கான ஒரு பொதுவான குறிக்கோள் PSNR ஆகும். இது மூல சட்டத்தை டிகோட் செய்யப்பட்ட சட்டகத்துடன் ஒப்பிடுகிறது. அதிக PSNR பொதுவாக சிறந்த தரத்தைக் குறிக்கிறது.
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
வரையறைகள் மற்றும் அடுத்த படிகள்
எங்கள் எளிய கோடெக் ஒரு சிறந்த தொடக்கமாகும், ஆனால் அது சரியானதல்ல. உண்மையான உலக கோடெக்குகளின் பரிணாமத்தை பிரதிபலிக்கும் சில வரம்புகள் மற்றும் சாத்தியமான மேம்பாடுகள் இங்கே உள்ளன:
- இயக்க மதிப்பீடு: எங்கள் விரிவான தேடல் மெதுவாகவும், அடிப்படையாகவும் உள்ளது. உண்மையான கோடெக்குகள் இயக்க திசையன்களை மிக வேகமாக கண்டுபிடிக்க அதிநவீன, படிநிலை தேடல் வழிமுறைகளைப் பயன்படுத்துகின்றன.
- B-பிரேம்கள்: நாங்கள் P-பிரேம்களை மட்டுமே செயல்படுத்தினோம். B-பிரேம்களைச் சேர்ப்பது சிக்கலான தன்மை மற்றும் லேட்டன்சியின் செலவில் சுருக்க திறனை கணிசமாக மேம்படுத்தும்.
- என்ட்ரோபி கோடிங்: நாங்கள் சரியான என்ட்ரோபி கோடிங் கட்டத்தை செயல்படுத்தவில்லை. பைத்தான் தரவு கட்டமைப்புகளை நாங்கள் வெறுமனே எடுத்தோம். குவாண்டிஸ் செய்யப்பட்ட பூஜ்ஜியங்களுக்கான ரன்-லென்த் என்கோடர் சேர்ப்பது, அதைத் தொடர்ந்து ஹஃப்மேன் அல்லது அரித்மெடிக் என்கோடர் சேர்ப்பது கோப்பு அளவை மேலும் குறைக்கும்.
- டிப்ளாக்கிங் வடிகட்டி: எங்கள் 8x8 தொகுதிகளுக்கு இடையிலான கூர்மையான விளிம்புகள் தெரியும் கலைப்பொருட்களை உருவாக்குகின்றன. நவீன கோடெக்குகள் இந்த விளிம்புகளை மென்மையாக்கவும், காட்சி தரத்தை மேம்படுத்தவும், மறுசீரமைப்புக்குப் பிறகு ஒரு டிப்ளாக்கிங் வடிகட்டியைப் பயன்படுத்துகின்றன.
- மாறி தொகுதி அளவுகள்: நவீன கோடெக்குகள் நிலையான 16x16 மேக்ரோப்ளாக்குகளைப் பயன்படுத்துவதில்லை. அவை உள்ளடக்கத்திற்கு சிறப்பாக பொருந்தக்கூடிய பல்வேறு தொகுதி அளவுகள் மற்றும் வடிவங்களுக்கு சட்டகத்தை தகவமைக்க முடியும் (எ.கா., தட்டையான பகுதிகளுக்கு பெரிய தொகுதிகளையும், விரிவான பகுதிகளுக்கு சிறிய தொகுதிகளையும் பயன்படுத்துதல்).
முடிவுரை
ஒரு வீடியோ கோடெக்கை உருவாக்குவது, எளிமைப்படுத்தப்பட்டதாக இருந்தாலும், மிகவும் பயனுள்ள பயிற்சியாகும். இது நமது டிஜிட்டல் வாழ்க்கையின் குறிப்பிடத்தக்க பகுதியை இயக்கும் தொழில்நுட்பத்தை நீக்குகிறது. நாம் ஸ்பேஷியல் மற்றும் டெம்போரல் மிதமிஞ்சிய தன்மையின் முக்கிய கருத்துகளின் மூலம் பயணம் செய்துள்ளோம், குறியீட்டு பைப்லைனின் அத்தியாவசிய கட்டங்கள் வழியாக நடந்து சென்றோம் - முன்னறிவிப்பு, மாற்றம் மற்றும் குவாண்டிசேஷன் - மேலும் இந்த யோசனைகளை பைத்தானில் செயல்படுத்தியுள்ளோம்.
இங்கு வழங்கப்பட்ட குறியீடு ஒரு ஆரம்ப புள்ளியாகும். இதை பரிசோதிக்க நான் உங்களை ஊக்குவிக்கிறேன். தொகுதி அளவு, குவாண்டிசேஷன் அளவுரு (`qp`) அல்லது GOP நீளத்தை மாற்ற முயற்சிக்கவும். ஒரு எளிய ரன்-லென்த் என்கோடிங் திட்டத்தை செயல்படுத்த முயற்சிக்கவும் அல்லது B-பிரேம்களைச் சேர்ப்பதற்கான சவாலை எதிர்கொள்ளவும். விஷயங்களை உருவாக்குவதன் மூலமும் உடைப்பதன் மூலமும், நாம் அடிக்கடி எடுத்துக்கொள்ளும் தடையற்ற வீடியோ அனுபவங்களுக்குப் பின்னால் உள்ள திறமைக்கு நீங்கள் ஆழ்ந்த பாராட்டைப் பெறுவீர்கள். வீடியோ சுருக்க உலகம் பரந்து விரிந்தது மற்றும் தொடர்ந்து உருவாகி வருகிறது, இது கற்றல் மற்றும் கண்டுபிடிப்புக்கான முடிவற்ற வாய்ப்புகளை வழங்குகிறது.