YUV 4:2:2格式2倍高效下采样算法求助(无需RGB转换)
Hey there! Let's break down what's almost certainly causing those repeated columns and color distortion issues when adapting a YUV 4:2:0 downsampling algorithm to 4:2:2. The core problem almost always stems from misunderstanding the fundamental layout differences between the two formats—let's dive in:
1. You’re Applying 4:2:0’s Vertical UV Downsampling Logic to 4:2:2
First, let’s clarify the key structural differences:
- YUV 4:2:0: U/V planes are both half the width and half the height of the Y plane (each 2x2 block of Y pixels shares one U and one V value).
- YUV 4:2:2: U/V planes are half the width of Y, but the same height (each pair of horizontal Y pixels shares one U/V, but every row of Y has a corresponding row of U/V).
If you copied 4:2:0’s logic of downsampling the U/V planes vertically (e.g., skipping every other row of U/V), you’re throwing away valid vertical color data that 4:2:2 actually provides. This immediately causes color distortion, and mismatched plane dimensions can lead to index errors that manifest as repeated columns.
2. Incorrect UV Pixel Index Mapping
For 2x downsampling, your output Y plane will be half the width and height of the input Y plane. But when mapping input Y pixels to their corresponding U/V values, you need to adjust for 4:2:2’s layout:
- For an input Y pixel at
(y_in, x_in), the corresponding U/V pixel is at(y_in, x_in // 2)(since horizontal Y pairs share one U/V, vertical rows align exactly). - If you’re using 4:2:0’s
y_in // 2for the U/V row index, you’re reusing the same U/V row for two rows of output Y—this causes vertical color banding and can shift indices enough to create repeated columns when your code wraps around plane boundaries.
3. Miscalculated Output Plane Dimensions
A common mistake is setting the output U/V plane dimensions to match the output Y plane. For 2x downsampling of 4:2:2:
- Input Y:
W x H→ Output Y:(W//2) x (H//2) - Input U/V:
(W//2) x H→ Output U/V:(W//4) x (H//2)
If you force output U/V to be (W//2) x (H//2), your code will either read beyond the input U/V plane’s bounds (causing repeated data when indices wrap) or pad with invalid values—both lead to those repeated columns and wonky colors.
Example Correct 2x Downsampling Logic (Pseudocode)
Here’s a simplified snippet to illustrate the right approach (using nearest-neighbor sampling for simplicity; you can swap in averaging for better quality):
// Input dimensions int in_w = ...; // Y plane width int in_h = ...; // Y plane height // Output dimensions (2x downsampled) int out_w = in_w / 2; int out_h = in_h / 2; int out_uv_w = out_w / 2; // U/V width is half output Y width // Input planes (Y: in_w x in_h; U/V: (in_w/2) x in_h) uint8_t* y_in = ...; uint8_t* u_in = ...; uint8_t* v_in = ...; // Output planes uint8_t* y_out = new uint8_t[out_w * out_h]; uint8_t* u_out = new uint8_t[out_uv_w * out_h]; uint8_t* v_out = new uint8_t[out_uv_w * out_h]; // Process Y plane: 2x2 block sampling for (int y = 0; y < out_h; y++) { for (int x = 0; x < out_w; x++) { // Pick top-left pixel of 2x2 Y block (or average all four) int in_y = y * 2; int in_x = x * 2; y_out[y * out_w + x] = y_in[in_y * in_w + in_x]; } } // Process U/V planes: no vertical downsampling needed beyond 2x Y downsample for (int y = 0; y < out_h; y++) { for (int x = 0; x < out_uv_w; x++) { // Map to input U/V: vertical index matches input Y's downsampled row, horizontal is 2x output UV index int in_y = y * 2; int in_x = x * 2; u_out[y * out_uv_w + x] = u_in[in_y * (in_w/2) + in_x]; v_out[y * out_uv_w + x] = v_in[in_y * (in_w/2) + in_x]; } }
Check your code for these three key issues—chances are you’re mixing up plane dimensions or index mappings from the 4:2:0 implementation. Once you align the logic to 4:2:2’s horizontal-only UV subsampling, those repeated columns and color artifacts should disappear.
内容的提问来源于stack exchange,提问作者James Harcourt

