【一步步開發AI運動小程式】十九、運動識別中如何解析RGBA幀圖片?

alphaair發表於2024-07-09

引言 最近有不少開發者向我們諮詢,像體測、賽事等應用場景中,需要儲存運動過程的影像,如何將相機抽取的RGBA幀影像解析成.jpg.png格式的影像?今天我們就為您介紹相應的解決方案。

一、RGBA影像結構。

RGBA影像為一維陣列,每四個元素描寫一個影像畫素,前三元素為顏色值,第四個元素為透明度值,按列掃描順序分佈,如下圖所示,為一個寬2px、高3px的結果,如下圖所示:
image
image

二、相關API。

根據上面的影像結構,我們把相應的畫素點在canvas上畫出來即可。為了減少繪製時對介面的干擾,我們使用uni.createOffsetScreen()建立離屏畫布繪製。
image

三、程式碼實現。

實現程式碼如下,抽幀程式碼見前面的抽幀章節。

...
onCameraReady(e) {
	const context = wx.createCameraContext();
	const listener = context.onCameraFrame(frame => {
		this.parseToJpeg(frame);
	});
	listener.start();
}
parseToJpeg(){
	const canvas = uni.createOffscreenCanvas({
		width: frame.width,
		height: frame.height,
		type: '2d'
	});
	
	let offset = 0;
	let gl = canvas.getContext('2d');
	const buffer = frame.data;
	for (let y = 0; y < frame.height; y++) {
		for (let x = 0; x < frame.width; x++) {
			let r = buffer[offset].toString(16).padStart(2, '0');
			let g = buffer[offset + 1].toString(16).padStart(2, '0');
			let b = buffer[offset + 2].toString(16).padStart(2, '0');
			let a = buffer[offset + 3].toString(16).padStart(2, '0');

			let color = `#${r}${g}${b}${a}`;
			//console.log(color, offset);
			gl.fillStyle = color;
			gl.fillRect(x, y, 1, 1);

			offset += 4;
		}
	}
}
...

四、後記

4.1、為什麼不直接使用拍照API?

這主要出於兩個原因,一是在抽幀的同時無法呼叫CameraContext.takePhoto()API進行拍照; 二是由於抽幀是非同步的,所以無法同步呼叫,可能會導致識別時機的影像與拍攝的一不致。

4.2、影像轉換呼叫頻率。

由於影像轉換是比較消耗計算資源的,所以建議不要在抽幀時同步呼叫影像轉換,建議先暫存要轉換的幀,等運動結束是再進行轉換、上傳等操作。

相關文章