?案例1?綠邊

故障分析:
這個能明顯看到視頻上方出現綠色半透明邊帶。這說明Y數據正常。UV數據不正常。
它顯然與視頻幀的垂直分辨率設置有關。
UV數據和Y數據是連續放置的,如果上方出現彩色數據失調,說明這部分數據實際仍然是Y數據。也就是說如果這是1920*1080p的數據,那么說明它的線數比1080更大。
根據綠邊行數/2,加至1080的數據上,故障消失:
案例2?柵格
故障分析
上面的配置下,出現水平數據的錯位,在上面可以正常的顯示被拆分成了3個帶狀的數據。YUV模式下不好看故障的特征,先把UV數據消掉,用標準的灰度圖像去觀察:
相關的灰度UV數據生成:
uv_plane = np.full((height // 2, width), 128, dtype=np.uint8)
最終根據灰度圖上的關鍵點位的相對位置,得到了真正的width,修正后:
?
附錄 A 16*16宏塊分散的視頻數據重組為標準YUV-420
這段代碼沒有用到,備用。本來是為了處理案例2.
def merge_to_yuv420(self, macrobloc_data, width, height):# Calculate sizesY_size = width * heightU_size = Y_size // 4 # U and V are quarter size of Y# Initialize arrays for Y, U, VY = np.empty((height, width), dtype=np.uint8)U = np.empty((height // 2, width // 2), dtype=np.uint8)V = np.empty((height // 2, width // 2), dtype=np.uint8)# Merge macroblocks into Y, U, V componentsfor r in range(height // 16):for c in range(width // 16):macroblock_index = r * (width // 16) + cY_block_start = macroblock_index * 256U_block_start = Y_size + (macroblock_index * 64)V_block_start = Y_size + U_size + (macroblock_index * 64)# Merge Y blockY[r*16:(r+1)*16, c*16:(c+1)*16] = np.frombuffer(macrobloc_data[Y_block_start:Y_block_start+256], dtype=np.uint8).reshape(16, 16)# Merge U and V blocksU[r*8:(r+1)*8, c*8:(c+1)*8] = np.frombuffer(macrobloc_data[U_block_start:U_block_start+64], dtype=np.uint8).reshape(8, 8)V[r*8:(r+1)*8, c*8:(c+1)*8] = np.frombuffer(macrobloc_data[V_block_start:V_block_start+64], dtype=np.uint8).reshape(8, 8)return Y, U, Vdef nv12_to_rgb(self, nv12, width, height):width = 1920height = 1080Y,U,V = self.merge_to_yuv420(nv12, width, height)U_upsampled = cv2.resize(U, (width, height), interpolation=cv2.INTER_LINEAR)V_upsampled = cv2.resize(V, (width, height), interpolation=cv2.INTER_LINEAR)yuv_image = np.concatenate((Y, U_upsampled, V_upsampled))# Use OpenCV to convert YUV420sp (NV12) to RGBrgb_image = cv2.cvtColor(yuv_image, cv2.COLOR_YUV2RGB_IYUV)return rgb_image