React-Native制作一个通过照片和视频识别鸟类的安卓app

​

前言

首先简单介绍一下这个app是干啥的,实际上我的标题已经差不多说完了.....就是用户可以上传带有鸟类的图片或者视频,然后就可以得到相应的识别效果,这个app的需求是来自于我的一位朋友,所以我就做出来了

正文

讲一下基本用到的技术栈吧,前端用的react-native,后端用的是flask,识别算法部分用的是yolov5,接下来我会从三个大方面讲一下学到的东西,也就是前端后端和识别算法这三个大方面.

前端

前端实际上是我第二次使用rn,算是有点经验了其实,这次我就直接用原生的rn框架创建了,而不是使用上次坑了我一次的expo框架.....,然后这次我又新学了一些东西

图标的使用

原先我想用图标总是傻傻的去用npm下载下来的库里的icon,然而这样非常的麻烦,经常出现失败的情况,而且搞不好要不去Android那个文件夹改一堆链接,于是我直接去例如iconfont-阿里巴巴矢量图标库这样的网站去下载png图标资源,然后用img标签展示就行,这样简单多了,唯一需要注意的大概就是记得把图片的名称改成英文的就成,不然打包的时候似乎会出问题....

redux的使用

有一说一,这是我第一次用redux,这里简单说一下redux的用法:

Redux是JavaScript的一个状态管理库,通常与React一起使用

它通过 centerX 全局单一的状态树state tree来存储整个应用的状态。改变状态的唯一方式就是触发动作action,动作是一个描述发生了什么的纯对象。

Redux 的主要组成部分包括:

  1. Store:存储应用的完整状态。想象它就像你应用的"数据库"。

  2. Actions:表示一种对状态做出改变的方式。在Redux中,所有的改变都被明确化为动作。它们是一个带有 type属性和额外数据的简单JavaScript对象。

  3. Reducers: 是改变状态的唯一方式,其是纯函数,接收旧的 state 和一个 action,然后返回新的 state。 关于Redux的基本使用步骤如下:

Step 1:创建 Actions

javascript 复制代码
export const SOME_ACTION = 'SOME_ACTION';

export function doSomething()

{ return { type: SOME_ACTION, payload: "Action data" } }

Step 2:创建 Reducers

javascript 复制代码
import { SOME_ACTION } from '../actions/sampleActions';

export default function sampleReducer(state = initialState, action)

{ switch (action.type) { case SOME_ACTION: return Object.assign({}, state, action.payload); default: return state; } }

Step 3:创建 Store

javascript 复制代码
 import { createStore } from 'redux';

import rootReducer from './reducers';

let store = createStore(rootReducer);

Step 4:使用 Store

javascript 复制代码
import { Provider } from 'react-redux';

import { createStore } from 'redux';

import rootReducer from './reducers';

import App from './components/App';

let store = createStore(rootReducer);

render(

<Provider store={store}>

<App />

</Provider>,

document.getElementById('root') );

Step 5:在你的组件中使用 Redux Actions

javascript 复制代码
import { connect } from 'react-redux';

import { doSomething } from './actions/sampleActions';

function mapStateToProps(state){ return { stateProp: state.stateProp }; }

function mapDispatchToProps(dispatch){

return { doSomething: () => dispatch(doSomething())

}; }

class MyComponent extends React.Component{ componentDidMount(){ this.props.doSomething(); } render(){ // Render using this.props.stateProp and this.props.doSomething } }

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent); 

一些小吐槽

rn在很多方面挺方便的,但是我用下来总有些隔靴搔痒之感....或许之后我会转向原生的安卓开发()

后端

后端我是第一次用flask,所以先学了一下,大概了解了一下基本接口怎么写和怎么连接数据库就开写了,毕竟我本质上是crud,感觉基本需要说的就大概是怎么调用脚本

脚本调用

这里因为我用了python的虚拟环境,所以不能直接用python驱动脚本,而是要用特定的虚拟环境下的python文件来驱动,这里是一点需要注意的.然后

python 复制代码
@app.route('/video', methods=['POST'])
def video():
    print("Video route started.")
    
    if 'video' not in request.files:
        return 'No video file part', 400

    file = request.files['video']
    if file.filename == '':
        return 'No video file selected', 400
    
    temp_dir = tempfile.TemporaryDirectory() 
    input_video_path = os.path.join(temp_dir.name, 'input.mp4')

    file.save(input_video_path) 
    print(f"Saved video file to {input_video_path}")

    result = run_yolo_video(input_video_path) 

    temp_dir.cleanup()
    
    return jsonify({"data": result}), 200

def run_yolo_video(input_video_path): 
    print("YOLO video function started.")
    model_path = "/etc/nginx/code/birdsearch/yolov5/weights/best.pt"
    command = f"python ../yolov5/detect.py --weights {model_path} --source {input_video_path}"
    print(f"Running command {command}")
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
    output = stderr.decode("utf-8")
    print(f"Received output: {output}")

    return output

然后需要讲一下大概就是我这边读取控制台输出的操作:

这个函数 run_yolo_video(input_video_path) 是用来通过 YOLO (You Only Look Once) 模型对输入路径下的视频进行对象检测的。

解读这个函数:

  1. print("YOLO video function started."): 输出提示信息,表示 YOLO 视频函数已经开始运行。

  2. model_path = "/etc/nginx/code/birdsearch/yolov5/weights/best.pt": 这一行定义了模型路径。也就是说,YOLO 模型权重文件被存储在 "/etc/nginx/code/birdsearch/yolov5/weights/best.pt" 路径下。

  3. command = f"python ../yolov5/detect.py --weights {model_path} --source {input_video_path}": 通过 Python 运行 YOLO 定位脚本 detect.py。--weights {model_path}选项指定了模型权重文件的路径。--source {input_video_path}选项则定义了要处理的输入视频的路径。

  4. print(f"Running command {command}"): 打印将要运行的命令。

  5. process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE): 使用 subprocess 模块运行上面定义的命令。Popen 函数创建一个新的进程来运行这个命令,shell=True 参数表示通过 shell 运行该命令,stdout=subprocess.PIPE 和 stderr=subprocess.PIPE 则表示我们想要捕获命令的标准输出和错误输出。

  6. stdout, stderr = process.communicate(): communicate 方法等待进程结束,然后返回一个元组,包含进程的标准输出和错误输出。

  7. output = stderr.decode("utf-8"): decode 函数将错误输出(该输出以字节形式存在)转换为字符串。

  8. print(f"Received output: {output}"): 打印从 detect.py 脚本收到的输出。

yolov5算法

这个其实没啥好说的,就是找开源数据集然后设置好参数,用yolov5train就完事了,很简单,我还租了一个4090服务器进行训练,这样快一点()

结语

总之这个项目顺利完结了,最终打包的apk也给我的那位朋友了,总之差不多就是这样!!!!

​

相关推荐
变与不变8066 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半7 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck7 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.7 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子7 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常7 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常7 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋7 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发8 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos
屏什么录8 小时前
录屏超过两小时就卡顿崩盘?从参数调优到代码实现,一文彻底搞定长时间录屏
前端·音视频开发