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

将带构造函数的React Native模糊检测类组件转为函数组件

React Native 类组件转函数组件:图像模糊检测实现

以下是将原类组件迁移为函数组件的完整实现,保留了拍照、模糊检测核心功能,适配React Hooks语法:

import React, { useState, useEffect, useRef } from 'react';
import { View, Button, Text, StyleSheet } from 'react-native';
import { Camera } from 'react-native-camera';
import OpenCV from 'react-native-opencv';

const CameraScreen = ({ navigation }) => {
  // 替换类组件state为useState钩子
  const [isCameraReady, setIsCameraReady] = useState(false);
  const [hasPermission, setHasPermission] = useState(null);
  const [isTakingPhoto, setIsTakingPhoto] = useState(false);
  const [blurLevel, setBlurLevel] = useState(null);
  const camera = useRef(null);

  // 替换componentDidMount的权限请求逻辑
  useEffect(() => {
    const requestCameraPermission = async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === 'granted');
    };
    requestCameraPermission();
  }, []);

  // 拍照逻辑
  const takePicture = async () => {
    if (!isCameraReady || isTakingPhoto) return;
    
    setIsTakingPhoto(true);
    try {
      const photo = await camera.current.takePictureAsync({ quality: 0.8 });
      await detectBlur(photo.uri);
    } catch (error) {
      console.error('拍照失败:', error);
    } finally {
      setIsTakingPhoto(false);
    }
  };

  // 模糊检测核心逻辑(基于OpenCV)
  const detectBlur = async (imageUri) => {
    try {
      // 加载图像并转灰度图
      const mat = await OpenCV.imreadAsync(imageUri);
      const grayMat = await OpenCV.cvtColorAsync(mat, OpenCV.COLOR_RGBA2GRAY);
      
      // 用Laplacian算子计算边缘方差,方差越小图像越模糊
      const laplacian = await OpenCV.LaplacianAsync(grayMat, OpenCV.CV_64F);
      const { stdDev } = await OpenCV.meanStdDevAsync(laplacian);
      const blurValue = stdDev[0] ** 2;

      // 根据阈值划分模糊等级
      if (blurValue < 10) {
        setBlurLevel('图像模糊');
      } else if (blurValue < 50) {
        setBlurLevel('图像轻度模糊');
      } else {
        setBlurLevel('图像清晰');
      }

      // 释放OpenCV Mat资源,避免内存泄漏
      await OpenCV.releaseAsync(mat);
      await OpenCV.releaseAsync(grayMat);
      await OpenCV.releaseAsync(laplacian);
    } catch (error) {
      console.error('模糊检测失败:', error);
      setBlurLevel('检测失败');
    }
  };

  if (hasPermission === null) {
    return <View />;
  }
  if (hasPermission === false) {
    return <Text>没有相机权限</Text>;
  }

  return (
    <View style={styles.container}>
      <Camera
        ref={camera}
        style={styles.camera}
        onCameraReady={() => setIsCameraReady(true)}
        type={Camera.Constants.Type.back}
      />
      <View style={styles.buttonContainer}>
        <Button
          title={isTakingPhoto ? '拍照中...' : '拍照'}
          onPress={takePicture}
          disabled={isTakingPhoto || !isCameraReady}
        />
      </View>
      {blurLevel && <Text style={styles.blurText}>检测结果: {blurLevel}</Text>}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  camera: {
    flex: 1,
    width: '100%',
  },
  buttonContainer: {
    position: 'absolute',
    bottom: 50,
    width: '100%',
    alignItems: 'center',
  },
  blurText: {
    position: 'absolute',
    top: 20,
    fontSize: 18,
    color: 'white',
    backgroundColor: 'rgba(0,0,0,0.7)',
    padding: 8,
    borderRadius: 4,
  },
});

export default CameraScreen;

核心迁移点说明

  1. 状态管理:将类组件的this.state拆分为多个useState钩子,实现更细粒度的状态控制,避免this绑定问题。
  2. 生命周期适配:原componentDidMount中的权限请求逻辑,迁移到useEffect钩子(空依赖数组确保仅初始化执行一次)。
  3. 实例引用:用useRef获取相机组件实例,替代类组件的this.camera。
  4. 方法重构:原类组件的类方法全部改为函数组件内部的异步函数,逻辑完全保留,写法更简洁。
  5. OpenCV逻辑复用:完整保留了基于Laplacian算子的模糊检测核心逻辑,同时添加了Mat资源释放步骤,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Ronuel Banderada Moralita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:36:30