You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 16:15:01