如何在tfjs-react-native中自动获取Android设备Camera Texture分辨率
安卓端tfjs-react-native相机纹理分辨率自动获取方案
以下是两种可直接落地的适配方案,可完全解决安卓机型差异导致的关键点偏移问题:
方案1:预先查询相机支持的预览尺寸动态赋值
利用expo-camera提供的getAvailableCameraSizesAsync接口,在组件初始化时查询当前使用相机(前置/后置)的所有支持预览尺寸,匹配与你的预览视图宽高比最接近的尺寸作为纹理参数,避免硬编码:
import { Camera } from 'expo-camera'; import { cameraWithTensors } from '@tensorflow/tfjs-react-native'; import { Platform } from 'react-native'; const TensorCamera = cameraWithTensors(Camera); class MyComponent { state = { textureDims: null, isCameraReady: false } async componentDidMount() { // 查询当前前置相机支持的所有预览尺寸 const cameraType = Camera.Constants.Type.front; const availableSizes = await Camera.getAvailableCameraSizesAsync(cameraType); // 你的预览视图宽高比,按实际布局调整 const targetRatio = styles.camera.width / styles.camera.height; // 筛选最接近目标比例的最大尺寸,平衡性能和识别精度 const matchedSize = availableSizes .map(size => ({ ...size, // 计算尺寸比例和目标比例的差值,安卓预览尺寸默认是横屏宽高比 diff: Math.abs((size.width / size.height) - targetRatio) })) .sort((a, b) => a.diff - b.diff || b.width - a.width)[0]; let finalDims; if (Platform.OS === 'ios') { finalDims = { height: 1920, width: 1080 }; } else { // 竖屏应用需要交换宽高,和预览方向对齐 finalDims = { height: matchedSize.width, width: matchedSize.height } } this.setState({ textureDims: finalDims, isCameraReady: true }); } handleCameraStream(images, updatePreview, gl) { const loop = async () => { const nextImageTensor = images.next().value // 张量处理逻辑 requestAnimationFrame(loop); } loop(); } render() { const { isCameraReady, textureDims } = this.state; if (!isCameraReady) return null; return <View> <TensorCamera style={styles.camera} type={Camera.Constants.Type.front} cameraTextureHeight={textureDims.height} cameraTextureWidth={textureDims.width} resizeHeight={200} resizeWidth={152} resizeDepth={3} onReady={this.handleCameraStream} autorender={true} /> </View> } }
方案2:通过输出张量的实际尺寸校准坐标
如果不想动态修改TensorCamera的参数,可以直接从输出的张量中读取实际尺寸,后续关键点坐标换算统一使用该实际尺寸,完全规避硬编码参数导致的偏移问题:
// 在handleCameraStream中新增校准逻辑 handleCameraStream(images, updatePreview, gl) { let actualTextureDims = null; const loop = async () => { const nextImageTensor = images.next().value; // 首次运行时记录张量实际尺寸 if (!actualTextureDims) { const [tensorHeight, tensorWidth] = nextImageTensor.shape; actualTextureDims = { height: tensorHeight, width: tensorWidth }; } // *所有关键点坐标换算逻辑统一使用actualTextureDims,不使用硬编码的textureDims* // 示例坐标映射逻辑: // const previewX = keyPoint.x * (预览视图宽度 / actualTextureDims.width); // const previewY = keyPoint.y * (预览视图高度 / actualTextureDims.height); requestAnimationFrame(loop); } loop(); }
注意事项
- 安卓不同厂商的相机预览尺寸差异极大,不要使用统一硬编码值,以上两种方案都可以覆盖99%以上的机型
- 如果你的应用支持横竖屏切换,需要在屏幕旋转时重新查询相机尺寸或重新校准张量尺寸,避免坐标偏移
- 优先推荐方案2,无需额外调用系统接口,适配性更强,完全不会出现因纹理参数错误导致的关键点偏移问题
内容的提问来源于stack exchange,提问作者Raj Mahoula
相关产品推荐
相关产品推荐

