ಪೈಥಾನ್ ಬಳಸಿ ವೀಡಿಯೊ ಸಂಕೋಚನ ಅಲ್ಗಾರಿದಮ್ಗಳನ್ನು ಮೊದಲಿನಿಂದಲೂ ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಮತ್ತು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ. ಆಧುನಿಕ ವೀಡಿಯೊ ಕೋಡೆಕ್ಗಳ ಹಿಂದಿನ ಸಿದ್ಧಾಂತ ಮತ್ತು ಆಚರಣೆಯನ್ನು ತಿಳಿಯಿರಿ.
ಪೈಥಾನ್ನಲ್ಲಿ ವೀಡಿಯೊ ಕೋಡೆಕ್ ಅನ್ನು ನಿರ್ಮಿಸುವುದು: ಸಂಕೋಚನ ಅಲ್ಗಾರಿದಮ್ಗಳ ಆಳವಾದ ವಿಶ್ಲೇಷಣೆ
ನಮ್ಮ ಅತಿ-ಸಂಪರ್ಕಿತ ಜಗತ್ತಿನಲ್ಲಿ, ವೀಡಿಯೊವೇ ರಾಜ. ಸ್ಟ್ರೀಮಿಂಗ್ ಸೇವೆಗಳು ಮತ್ತು ವೀಡಿಯೊ ಕಾನ್ಫರೆನ್ಸಿಂಗ್ನಿಂದ ಹಿಡಿದು ಸಾಮಾಜಿಕ ಮಾಧ್ಯಮ ಫೀಡ್ಗಳವರೆಗೆ, ಡಿಜಿಟಲ್ ವೀಡಿಯೊ ಅಂತರ್ಜಾಲದ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಆಳುತ್ತದೆ. ಆದರೆ ಪ್ರಮಾಣಿತ ಅಂತರ್ಜಾಲ ಸಂಪರ್ಕದ ಮೂಲಕ ಹೈ-ಡೆಫಿನಿಷನ್ ಚಲನಚಿತ್ರವನ್ನು ಕಳುಹಿಸುವುದು ಹೇಗೆ ಸಾಧ್ಯ? ಇದಕ್ಕೆ ಉತ್ತರವು ಆಕರ್ಷಕ ಮತ್ತು ಸಂಕೀರ್ಣ ಕ್ಷೇತ್ರದಲ್ಲಿದೆ: ವೀಡಿಯೊ ಸಂಕೋಚನ. ಈ ತಂತ್ರಜ್ಞಾನದ ಹೃದಯಭಾಗದಲ್ಲಿ ವೀಡಿಯೊ ಕೋಡೆಕ್ (COder-DECoder) ಇದೆ, ಇದು ದೃಶ್ಯ ಗುಣಮಟ್ಟವನ್ನು ಕಾಪಾಡಿಕೊಳ್ಳುವಾಗ ಫೈಲ್ ಗಾತ್ರವನ್ನು ತೀವ್ರವಾಗಿ ಕಡಿಮೆ ಮಾಡಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾದ ಅತ್ಯಾಧುನಿಕ ಅಲ್ಗಾರಿದಮ್ಗಳ ಸಮೂಹವಾಗಿದೆ.
H.264, HEVC (H.265) ಮತ್ತು ರಾಯಲ್ಟಿ-ಮುಕ್ತ AV1 ನಂತಹ ಉದ್ಯಮ-ಪ್ರಮಾಣಿತ ಕೋಡೆಕ್ಗಳು ನಂಬಲಾಗದಷ್ಟು ಸಂಕೀರ್ಣ ಎಂಜಿನಿಯರಿಂಗ್ ತುಣುಕುಗಳಾಗಿದ್ದರೂ, ಅವುಗಳ ಮೂಲಭೂತ ತತ್ವಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಯಾವುದೇ ಪ್ರೇರಿತ ಡೆವಲಪರ್ಗೆ ಸುಲಭವಾಗಿ ಲಭ್ಯವಿದೆ. ಈ ಮಾರ್ಗದರ್ಶಿ ನಿಮ್ಮನ್ನು ವೀಡಿಯೊ ಸಂಕೋಚನದ ಜಗತ್ತಿನಲ್ಲಿ ಆಳವಾದ ಪ್ರಯಾಣಕ್ಕೆ ಕರೆದೊಯ್ಯುತ್ತದೆ. ನಾವು ಸಿದ್ಧಾಂತದ ಬಗ್ಗೆ ಮಾತ್ರ ಮಾತನಾಡುವುದಿಲ್ಲ; ನಾವು ಪೈಥಾನ್ ಬಳಸಿ ಸರಳೀಕೃತ, ಶೈಕ್ಷಣಿಕ ವೀಡಿಯೊ ಕೋಡೆಕ್ ಅನ್ನು ಮೊದಲಿನಿಂದ ನಿರ್ಮಿಸುತ್ತೇವೆ. ಆಧುನಿಕ ವೀಡಿಯೊ ಸ್ಟ್ರೀಮಿಂಗ್ ಅನ್ನು ಸಾಧ್ಯವಾಗಿಸುವ ಸೊಗಸಾದ ಕಲ್ಪನೆಗಳನ್ನು ಗ್ರಹಿಸಲು ಈ ಪ್ರಾಯೋಗಿಕ ವಿಧಾನವು ಉತ್ತಮ ಮಾರ್ಗವಾಗಿದೆ.
ಪೈಥಾನ್ ಏಕೆ? ನೈಜ-ಸಮಯದ, ಹೆಚ್ಚಿನ-ಕಾರ್ಯಕ್ಷಮತೆಯ ವಾಣಿಜ್ಯ ಕೋಡೆಕ್ಗಾಗಿ (ಇವುಗಳನ್ನು ಸಾಮಾನ್ಯವಾಗಿ C/C++ ಅಥವಾ ಅಸೆಂಬ್ಲಿಯಲ್ಲಿ ಬರೆಯಲಾಗುತ್ತದೆ) ನೀವು ಬಳಸುವ ಭಾಷೆ ಇದಲ್ಲದಿದ್ದರೂ, ಪೈಥಾನ್ನ ಓದುವಿಕೆ ಮತ್ತು ಅದರ ಪ್ರಬಲ ಲೈಬ್ರರಿಗಳಾದ NumPy, SciPy ಮತ್ತು OpenCV ಕಲಿಕೆ, ಮೂಲಮಾದರಿ ರಚನೆ ಮತ್ತು ಸಂಶೋಧನೆಗೆ ಸೂಕ್ತ ವಾತಾವರಣವನ್ನು ಒದಗಿಸುತ್ತವೆ. ನೀವು ಕಡಿಮೆ-ಮಟ್ಟದ ಮೆಮೊರಿ ನಿರ್ವಹಣೆಯಲ್ಲಿ ಸಿಲುಕಿಕೊಳ್ಳದೆ ಅಲ್ಗಾರಿದಮ್ಗಳ ಮೇಲೆ ಗಮನ ಹರಿಸಬಹುದು.
ವೀಡಿಯೊ ಸಂಕೋಚನದ ಮೂಲಭೂತ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು
ನಾವು ಒಂದೇ ಒಂದು ಕೋಡ್ ಸಾಲನ್ನು ಬರೆಯುವ ಮೊದಲು, ನಾವು ಏನನ್ನು ಸಾಧಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದೇವೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಬೇಕು. ವೀಡಿಯೊ ಸಂಕೋಚನದ ಗುರಿ ಪುನರಾವರ್ತಿತ ಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕುವುದು. ಕಚ್ಚಾ, ಅಸಂಕೋಚಿಸಿದ ವೀಡಿಯೊ ದೊಡ್ಡದಾಗಿದೆ. 30 ಫ್ರೇಮ್ಪ್ರತಿ ಸೆಕೆಂಡ್ಗೆ ಒಂದು ನಿಮಿಷದ 1080p ವೀಡಿಯೊ 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: ಕ್ವಾಂಟೈಸೇಷನ್
ಇದು ಪೈಪ್ಲೈನ್ನಲ್ಲಿನ ಪ್ರಾಥಮಿಕ ನಷ್ಟಭರಿತ ಹಂತವಾಗಿದೆ ಮತ್ತು ಗುಣಮಟ್ಟ-Vs-ಬಿಟ್ರೇಟ್ ವ್ಯಾಪಾರ-ವ್ಯವಹಾರವನ್ನು ನಿಯಂತ್ರಿಸಲು ಪ್ರಮುಖವಾಗಿದೆ. 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-ಫ್ರೇಮ್ಗಳನ್ನು ಸೇರಿಸುವ ಸವಾಲನ್ನು ನಿಭಾಯಿಸಿ. ವಿಷಯಗಳನ್ನು ನಿರ್ಮಿಸುವ ಮತ್ತು ಮುರಿಯುವ ಮೂಲಕ, ನಾವು ಸಾಮಾನ್ಯವಾಗಿ ಸಾಮಾನ್ಯವೆಂದು ಭಾವಿಸುವ ತಡೆರಹಿತ ವೀಡಿಯೊ ಅನುಭವಗಳ ಹಿಂದಿನ ತಾಂತ್ರಿಕ ಚಾತುರ್ಯಕ್ಕಾಗಿ ನೀವು ಆಳವಾದ ಮೆಚ್ಚುಗೆಯನ್ನು ಪಡೆಯುತ್ತೀರಿ. ವೀಡಿಯೊ ಸಂಕೋಚನದ ಜಗತ್ತು ವಿಶಾಲವಾಗಿದೆ ಮತ್ತು ನಿರಂತರವಾಗಿ ವಿಕಸಿಸುತ್ತಿದೆ, ಕಲಿಕೆ ಮತ್ತು ಆವಿಷ್ಕಾರಗಳಿಗೆ ಅಂತ್ಯವಿಲ್ಲದ ಅವಕಾಶಗಳನ್ನು ನೀಡುತ್ತದೆ.