老周有AI

计算机视觉与人工智能技术分享

问题

cv2.imshow 显示图像时报错,无法显示图像

  0%|                                                                                                                                                                          | 0/1 [00:00<?, ?it/s]
Traceback (most recent call last):
  File "/home/xxx/workspace/inference.py", line 380, in <module>
    cv2.imshow('result', img)
cv2.error: OpenCV(4.8.0) /io/opencv/modules/highgui/src/window.cpp:1272: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'

貌似因为之前 pip3 install opencv-python-headless 安装后导致版本不一致了。

解决方案

pip3 uninstall opencv-python
pip3 install opencv-python-contrib
pip3 install opencv-python

参考引用

解决问题:If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then…‘cvShowImage‘

一、rknn 模型的导出

请参考其他博客和仓库;

CSDN 黄金旺铺

训练与导出仓库

github仓库

二、测试验证

  1. git clone 仓库到本地

rk3588_yolov5_deploy

git clone https://github.com/wangqiqi/rk3588_yolov5_deploy.git

NOTE: 此处说的本地就是开发板,需要将开发板联网,并配置相关git信息

  1. 编译安装
bash build_rk3588_yolov5.sh
  1. 测试
bash test_rk3588_yolov5.sh

三、rknn 部署自己的模型和项目

  1. 将导出的 rknn 模型,放到 assets 文件夹下;
  2. 修改 assets/labels_list.txt 文件,将训练的目标类别名称分行存储;
  3. 添加测试图片到 assets 文件夹下;
  4. 根据项目需要,修改文件中相关信息

文件 yolov5/include/postprocess.hline 7~11

#define OBJ_NAME_MAX_SIZE 16  // 最长目标名称
#define OBJ_NUMB_MAX_SIZE 64  // 最多目标个数
#define OBJ_CLASS_NUM 1       // 目标类别数--需要根据项目进行修改
#define NMS_THRESH 0.45       // NMS 阈值
#define BOX_THRESH 0.25       // 目标置信度
  1. 编译安装与测试
bash build_rk3588_yolov5.sh

修改脚本test_rk3588_yolov5.sh 中不同的模型和测试图片

set -e

ROOT_PWD=$( cd "$( dirname $0 )" && cd -P "$( dirname "$SOURCE" )" && pwd )
INSTALL_DIR=${ROOT_PWD}/install

cd ${INSTALL_DIR}
./rk3588_yolov5 assets/drp.rknn assets/drp.png
cd -

然后执行

bash test_rk3588_yolov5.sh

四、清理

bash clean_all.sh

保姆级教程,看这一篇就够用了。
在翻阅了网络上很多资料后,发现很多版本的信息比匹配。
花了一周的时间配置环境,以及环境验证,然后写了这篇长文。
有过程,有代码,有经验,欢迎大家批评指正。

一、环境准备

将宿主机和开发板接入同一个局域网,方便开发。

(一)宿主机

  1. PC电脑,x86_64, 带显卡, 配置不表, 能训练和开发即可。
  2. 系统: ubuntu 22.04 LTS 版本( ubuntu 18.04 LTS 以上)
  3. 自带的远程软件: Remmina 可以建立 ssh 连接,也可以建立 sftp 连接传输文件。
  4. Anaconda: 可以配置 python 开发的虚拟环境
  5. 需要在宿主机上安装 RKNN-Toolkit2

1. RKNN-Toolkit2

用于在 PC 端将用户训练的模型转换为 RKNN 模型。

RKNN-Toolkit2 是为用户提供在 PC 平台上进行模型转换、推理和性能评估的开发套件,用户通过该工具提供的Python 接口可以便捷地完成以下功能:

  • 模型转换:支持 Caffe、TensorFlow、TensorFlowLite、ONNX、DarkNet、PyTorch 等模型转为 RKNN 模型,并支持 RKNN 模型导入导出, RKNN 模型能够在 Rockchip NPU 平台上加载使用。
  • 量化功能:支持将浮点模型量化为定点模型,目前支持的量化方法为非对称量化(asymmetric_quantized-8),并支持混合量化功能。
  • 模型推理:能够在 PC(Linux x86平台)上模拟 Rockchip NPU 运行 RKNN 模型并获取推理结果;或将 RKNN 模型分发到指定的 NPU 设备上进行推理并获取推理结果。
  • 性能和内存评估:将 RKNN 模型分发到指定 NPU 设备上运行,以评估模型在实际设备上运行时的性能和内存占用情况。
  • 量化精度分析:该功能将给出模型量化前后每一层推理结果与浮点模型推理结果的余弦距离,以便于分析量化误差是如何出现的,为提高量化模型的精度提供思路。
  • 模型加密功能:使用指定的加密等级将 RKNN 模型整体加密。因为 RKNN 模型的加密是在 NPU 驱动中完成的,使用加密模型时,与普通 RKNN 模型一样加载即可, NPU 驱动会自动对其进行解密。

目前只支持 Ubuntu 18.04 LTS 以上版本系统。由于 github https://github.com/rockchip-linux/rknn-toolkit2 下载较慢,可以直接网盘下载:百度网盘-RKNN-Toolkit2 提取码: 8888

(二)开发板

  1. 整机,用的是 RK3588 整机。(NOTE: 我这里用的是定昌电子提供的整机,其他设备没有尝试
  2. 系统:ubuntu 20.04 LTS 版本
  3. 需要在开发板上安装 RKNPU2

1. RKNPU2

RKNPU2 提供了高级的接口访问 RockchipNPU ,可以在板端做很多应用。由于 github https://github.com/rockchip-linux/rknpu2 下载较慢,可以直接网盘下载: 百度网盘-RKNPU2 提取码: 8888

1.4.0

  • Support more NPU operators, such as Reshape、Transpose、MatMul、 Max、Min、exGelu、exSoftmax13、Resize etc.
  • Add Weight Share function, reduce memory usage.
  • Add Weight Compression function, reduce memory and bandwidth usage.(RK3588/RV1103/RV1106)
  • RK3588 supports storing weights or feature maps on SRAM, reducing system bandwidth consumption.
  • RK3588 adds the function of running a single model on multiple cores at the same time.
  • Add new output layout NHWC (C has alignment restrictions) .
  • Improve support for non-4D input.
  • Add more examples such as rknn_yolov5_android_apk_demo and rknn_internal_mem_reuse_demo.
  • Bug fix.

2. RKNN-Toolkit2-Lite

在板端测试运行

- RKNN-Toolkit-Lite2Rockchip NPU 平台(RK3566、RK3568、RK3588、RK3598S)提供 Python 编程接口,帮助用户部署 RKNN 模型并加速 AI 应用程序的实现。

刷机(非必要不刷机)

非必要不刷机,一般情况下购买的板子已经刷好了系统,可以直接运行,我这里只测试了一个板子,其他板子未确定环境是否符合要求。
刷机工具: 百度网盘-刷机工具 提取码: 8888
刷机系统: 百度网盘-刷机系统 提取码: 8888
刷机过程可以参考(过程类似):
【边缘设备】基于RK3399核心板的nanoPC-T4 线刷桌面版系统

二、环境验证

(一)板端验证

百度网盘-rknn_yolov5_rk3588_v14 提取码: 8888

在宿主机上打开 Remmina, 输入 IP地址,用户名,密码 连接开发板。将以上文件下载后,放到开发板上,并解压。
在这里插入图片描述
在这里插入图片描述
可以看到在 RK3588 上利用 NPU 运行 yolov5 模型,耗时在 33.8 ms 左右。板端环境已经具备。

(二)RKNN-Toolkit2-Lite(板端)

1. 安装 Miniconda

在板端下载 Miniconda, 版本为
在这里插入图片描述

bash Miniconda3-py39_23.3.1-0-Linux-aarch64.sh

一路安装直到成功。

2. 虚拟环境

板端安装完成后。创建并激活虚拟环境

conda create -n rknn python=3.9
conda activate rknn

进入 rknn_toolkit_lite2 目录,

3. 安装环境依赖

pip install packages/rknn_toolkit_lite2-1.4.0-cp39-cp39-linux_aarch64.whl

如果安装较慢,修改国内的 pip 源,

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

如果缺少其他包库,直接用 pip 进行安装。

4. 测试验证

进入目录 examples/inference_with_lite

执行 python test.py 即可。

至此,板端的 rknn_toolkit_lite2 已经安装和验证完毕。后续可以在板端进行开发和部署 python 程序。

NOTE

如果执行 python test.py 提示缺少 librknnrt.solibrga.so 库,请在 github 下载,或者在其他目录下将 librknnrt.solibrga.so 拷贝至 /usr/lib 目录中。

如果想在板端打开终端时默认启动 rknn 的虚拟环境,

vi ~/.bashrc

在里面添加 conda activate rknn

(三)宿主机

1. 创建并激活虚拟环境

安装 rknn 虚拟环境

conda create -n rknn python=3.8
conda activate rknn

安装 pytorch 虚拟环境

conda create -n pytorch

这里可以简单一点,创建 pytorch 环境的依赖, 也可以按照 pytorch 官方教程下载相应的包。

pip install ultralytics

缺啥补啥: pip install xx

2. 安装依赖

进入 rknn 虚拟环境, 并进入 rknn-toolkit2 目录,

source activate rknn
pip install -r doc/requirements_cp38-1.4.0.txt

requirements_cp38-1.4.0.txt 文件内容如下:

# if install failed, please change the pip source to 'https://mirror.baidu.com/pypi/simple'

# base deps
numpy==1.19.5
protobuf==3.12.2
flatbuffers==1.12

# utils
requests==2.27.1
psutil==5.9.0
ruamel.yaml==0.17.4
scipy==1.5.4
tqdm==4.64.0
bfloat16==1.1
opencv-python==4.5.5.64

# base
onnx==1.9.0
onnxoptimizer==0.2.7
onnxruntime==1.10.0
torch==1.10.1
torchvision==0.11.2
tensorflow==2.6.2

3. 安装环境

进入 rknn 虚拟环境, 并进入 rknn-toolkit2 目录

source activate rknn
pip install packages/rknn_toolkit2-1.4.0_22dcfef4-cp38-cp38-linux_x86_64.whl

4. 进入 rknn 虚拟环境, 并验证是否安装成功 rknn

source activate rknn

在这里插入图片描述

python 进入开发环境

from rknn.api import RKNN

没有报错,就说明 RKNN 已经安装成功。

5. 测试

宿主机上,进入 rknn 虚拟环境,

cd examples/onnx/yolov5/
tree .
.
├── bus.jpg
├── dataset.txt
├── test.py
└── yolov5s.onnx
python test.py

在这里插入图片描述

6. 将 rknn 模型放到板端验证

将上述步骤生成的 yolov5s.rknn 放到板端测试。

.
├── lib
│   ├── librga.so
│   └── librknnrt.so
├── model
│   ├── RK356X
│   │   └── yolov5s-640-640.rknn
│   ├── RK3588
│   │   ├── yolov5s-640-640.rknn
│   │   └── yolov5s.rknn
│   ├── RV110X
│   │   └── yolov5s-640-640.rknn
│   ├── bus.jpg
│   └── coco_80_labels_list.txt
├── out.jpg
├── rknn_yolov5_demo
└── testYolov5_rk3588.sh

修改 板端 文件

bash testYolov5_rk3588.sh 中的

./rknn_yolov5_demo model/RK3588/yolov5s-640-640.rknn model/bus.jpg

./rknn_yolov5_demo model/RK3588/yolov5s.rknn model/bus.jpg

并在板端执行 bash testYolov5_rk3588.sh

ztl@ztl:~/workspace/demo_rknn_yolov5_rk3588_v14$ bash testYolov5_rk3588.sh 
post process config: box_conf_threshold = 0.25, nms_threshold = 0.45
Read model/bus.jpg ...
img width = 640, img height = 640
Loading mode...
E RKNN: [05:25:08.050] failed to check rknpu hardware version: 0x46495245
E RKNN: [05:25:08.050] This rknn model is for RK3566, but current platform is RK3588
E RKNN: [05:25:08.050] rknn_init, load model failed!
rknn_init error ret=-1

出现报错信息,重新在宿主机平台上设置平台信息;

rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]])

修改为

rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rk3588')

并重新执行

python test.py

生成 yolov5s.rknn 模型并上传到板端对应位置。

重新在板端执行 bash testYolov5_rk3588.sh,运行效果正常。

至此,已经可以在 宿主机 上用给定的 demo 转换模型,并将模型上传到 板端 ,可以正确运行。

NOTE:共有四种方式开发和部署

  • 第一种是借助 RKNN-Toolkit2 的功能在模拟 NPU 上运行 RKNN 模型并获取推理结果(在PC端)
  • 第二种是借助 RKNN-Toolkit2 的功能, 将板子与 PC 连接,将 RKNN 模型分发到指定的 NPU 设备进行推理并获取推理结果(网络推理在板端,脚本写在 PC 端)
  • 第三种是调用 RKNN SDKC/C++ 语言 API 进行测试代码编写,并使用交叉编译器进行编译,将得到的可执行文件拷贝到板子上运行(开发编译在 PC 端,运行在板端),此处也可以通过 VS Code 连接板端,在板端开发应用。
  • 第四种是在板端安装 rknn-toolkit2-lite 工具,使用 python 脚本在板端推理(代码开发运行都在板端)

三、yolov5 训练自己的模型

(一)虚拟环境再次验证

我的电脑上有多个虚拟环境,一个是 pytorch ( 常用的深度学习框架的虚拟环境 ), 一个是 rknn( 就是之前安装 toolkit2 时新建的虚拟环境)。

pytorch虚拟环境信息

(base) jxx@desk:~$ source activate pytorch
(pytorch) jxx@desk:~$ python
Python 3.10.11 (main, Apr 20 2023, 19:02:41) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> import torchvision
>>> print(torch.__version__)
2.0.0+cu117
>>> print(torchvision.__version__)
0.15.1+cu117

rknn虚拟环境信息

(base) jxx@desk:~$ source activate rknn
(rknn) jxx@desk:~$ python
Python 3.8.16 (default, Mar  2 2023, 03:21:46) 
[GCC 11.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> import torchvision
>>> print(torch.__version__)
1.10.1+cu102
>>> print(torchvision.__version__)
0.11.2+cu102
>>> 

(二)仓库源码

直接下载 rknn_dev yolov5 github,并切换到 rknn_dev 分支

git clone https://github.com/wangqiqi/yolov5
git checkout rknn_dev # 切换到 rknn_dev 分支

预训练模型下载地址
yolov5s

(三)训练

1. 标注数据

可以用 cvat 或者 labelme 或者其他工具对检测数据进行标注。

yolov5 同级目录新建一个 datasets 文件夹,将标注好的数据打包到项目名称文件夹,然后放到 datasets 目录下,后续其他项目也可以同样进行。

2. 修改参数

(1)修改 ./data/proj.yaml

yolov5 文件下找到 data 目录,新建一个 proj.yaml 文件,类似于 drp.yaml

修改 proj.yaml 中的 ncnames;

nc: 类别数
names: 类别名称列表

(2)修改 config_onekey.sh

根据项目要求,修改 config_onekey.sh 文件中的相关参数;

例如:

__PRJNAME, __EPOCHSZ, __BATCHSZ, __IMSZ 等等。

3. 开始一键训练

前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch

下载预训练模型到 yolov5 同级目录 pre-trained 文件夹下,预训练模型下载地址

预训练模型下载地址
yolov5s

在训练之前确定 ./models/yolo.py 文件中的 class Detect(nn.Module):line:55forward 代码是否解注释了。

如果训练, forward 应为

    def forward(self, x):
        z = []  # inference output
        for i in range(self.nl):
            x[i] = self.m[i](x[i])  # conv
        
        ## 此处如果是训练, 请解开以下注释
            bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
            x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()

            if not self.training:  # inference
                if self.grid[i].shape[2:4] != x[i].shape[2:4] or self.onnx_dynamic:
                    self.grid[i] = self._make_grid(nx, ny).to(x[i].device)

                y = x[i].sigmoid()
                if self.inplace:
                    y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i]  # xy
                    y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]  # wh
                else:  # for YOLOv5 on AWS Inferentia https://github.com/ultralytics/yolov5/pull/2953
                    xy = (y[..., 0:2] * 2. - 0.5 + self.grid[i]) * self.stride[i]  # xy
                    wh = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i].view(1, self.na, 1, 1, 2)  # wh
                    y = torch.cat((xy, wh, y[..., 4:]), -1)
                z.append(y.view(bs, -1, self.no))

        return x if self.training else (torch.cat(z, 1), x)

开始一键训练
前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch

bash onekey_bash/train.sh

终端显示如下:

(base) jxxx@desk:~/workspace/algo/yolov5_rknn$ bash onekey_bash/train.sh 
train: weights=../pre-trained/yolov5s.pt, cfg=, data=data/drp.yaml, hyp=data/hyps/hyp.scratch.yaml, epochs=100, batch_size=32, imgsz=320, rect=True, resume=False, nosave=False, noval=False, noautoanchor=False, evolve=None, bucket=, cache=None, image_weights=False, device=, multi_scale=False, single_cls=False, adam=False, sync_bn=False, workers=8, project=runs/train, entity=None, name=drp, exist_ok=True, quad=False, linear_lr=False, label_smoothing=0.0, upload_dataset=False, bbox_interval=-1, save_period=-1, artifact_alias=latest, local_rank=-1, freeze=0, patience=100
github: ⚠️ YOLOv5 is out of date by 1203 commits. Use `git pull` or `git clone git@github.com:wangqiqi/yolov5` to update.
YOLOv5 🚀 c5360f6 torch 2.0.0+cu117 CUDA:0 (NVIDIA GeForce RTX 4090, 24209.125MB)

hyperparameters: lr0=0.01, lrf=0.2, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0
Weights & Biases: run 'pip install wandb' to automatically track and visualize YOLOv5 🚀 runs (RECOMMENDED)
TensorBoard: Start with 'tensorboard --logdir runs/train', view at http://localhost:6006/
Overriding model.yaml nc=80 with nc=1

                 from  n    params  module                                  arguments                     
  0                -1  1      3520  models.common.Focus                     [3, 32, 3]                    
  1                -1  1     18560  models.common.Conv                      [32, 64, 3, 2]                
  2                -1  1     18816  models.common.C3                        [64, 64, 1]                   
  3                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               
  4                -1  3    156928  models.common.C3                        [128, 128, 3]                 
  5                -1  1    295424  models.common.Conv                      [128, 256, 3, 2]              
  6                -1  3    625152  models.common.C3                        [256, 256, 3]                 
  7                -1  1   1180672  models.common.Conv                      [256, 512, 3, 2]              
  8                -1  1    656896  models.common.SPP                       [512, 512, [5, 9, 13]]        
  9                -1  1   1182720  models.common.C3                        [512, 512, 1, False]          
 10                -1  1    131584  models.common.Conv                      [512, 256, 1, 1]              
 11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          
 12           [-1, 6]  1         0  models.common.Concat                    [1]                           
 13                -1  1    361984  models.common.C3                        [512, 256, 1, False]          
 14                -1  1     33024  models.common.Conv                      [256, 128, 1, 1]              
 15                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']          
 16           [-1, 4]  1         0  models.common.Concat                    [1]                           
 17                -1  1     90880  models.common.C3                        [256, 128, 1, False]          
 18                -1  1    147712  models.common.Conv                      [128, 128, 3, 2]              
 19          [-1, 14]  1         0  models.common.Concat                    [1]                           
 20                -1  1    296448  models.common.C3                        [256, 256, 1, False]          
 21                -1  1    590336  models.common.Conv                      [256, 256, 3, 2]              
 22          [-1, 10]  1         0  models.common.Concat                    [1]                           
 23                -1  1   1182720  models.common.C3                        [512, 512, 1, False]          
 24      [17, 20, 23]  1     16182  models.yolo.Detect                      [1, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]]
 ....
 ....
 ....

     Epoch   gpu_mem       box       obj       cls    labels  img_size
     98/99     1.76G   0.02157  0.007322         0         3       320: 100%|███████████████████████████████████████████████████████████████████████████████████████████████| 59/59 [00:04<00:00, 13.07it/s]
               Class     Images     Labels          P          R     mAP@.5 mAP@.5:.95: 100%|███████████████████████████████████████████████████████████████████████████████| 30/30 [00:03<00:00,  7.54it/s]
                 all       1860       3277      0.979      0.962      0.991      0.727

     Epoch   gpu_mem       box       obj       cls    labels  img_size
     99/99     1.76G    0.0217  0.007213         0         3       320: 100%|███████████████████████████████████████████████████████████████████████████████████████████████| 59/59 [00:04<00:00, 12.90it/s]
               Class     Images     Labels          P          R     mAP@.5 mAP@.5:.95: 100%|███████████████████████████████████████████████████████████████████████████████| 30/30 [00:04<00:00,  6.66it/s]
                 all       1860       3277      0.979      0.967      0.992      0.737

100 epochs completed in 0.244 hours.
Optimizer stripped from runs/train/drp/weights/last.pt, 14.3MB
Optimizer stripped from runs/train/drp/weights/best.pt, 14.3MB
Results saved to runs/train/drp

(四)导出模型

前提条件: 已经创建了虚拟环境 rknn
前提条件: 已经创建了虚拟环境 rknn
前提条件: 已经创建了虚拟环境 rknn

问题及解决方案
解决 AttributeError: module ‘numpy‘ has no attribute ‘int‘ 训练yolo时的问题 原因:np.int在NumPy 1.20中已弃用,在NumPy 1.24中已删除。
一步真实解决RuntimeError: result type Float can‘t be cast to the desired output type long int

在训练之前确定 ./models/yolo.py 文件中的 class Detect(nn.Module):line:55forward 代码是否注释了。

此时应修改 forward 代码为:

    def forward(self, x):
        z = []  # inference output
        for i in range(self.nl):
            x[i] = self.m[i](x[i])  # conv
        return x # 此处如果是训练, 请注释

1. 修改参数

  1. 修改 config_onekey.sh 相关参数
  2. 将测试用的图片放到 export 文件夹下,修改 proj_dataset.txt 的内容为自己的图片列表

2. 开始一键导出

前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch
前提条件: 已经创建了虚拟环境 pytorch

bash onekey_bash/export_rknn.sh

终端显示如下:

(base) jxxx@desk:~/workspace/algo/yolov5_rknn$ bash onekey_bash/export_rknn.sh 
export: weights=runs/train/drp/weights/best.pt, img_size=[320], batch_size=1, device=cpu, include=['torchscript', 'onnx'], half=False, inplace=False, train=False, optimize=True, dynamic=False, simplify=True, opset=12
YOLOv5 🚀 c5360f6 torch 2.0.0+cu117 CPU

Fusing layers... 
Model Summary: 224 layers, 7053910 parameters, 0 gradients, 16.3 GFLOPs

PyTorch: starting from runs/train/drp/weights/best.pt (14.3 MB)

TorchScript: starting export with torch 2.0.0+cu117...
TorchScript: export success, saved as runs/train/drp/weights/best.torchscript.pt (28.3 MB)

ONNX: starting export with onnx 1.13.1...
...
...
I rknn buiding done
done
--> Export rknn model
done
--> Init runtime environment
W init_runtime: Target is None, use simulator!
done
(0.3333333333333333, 0.3333333333333333) 0.0 70.0
--> Running model
Analysing : 100%|███████████████████████████████████████████████| 161/161 [00:00<00:00, 5866.87it/s]
Preparing : 100%|█████████████████████████████████████████████████| 161/161 [00:04<00:00, 39.76it/s]
W inference: The dims of input(ndarray) shape (320, 320, 3) is wrong, expect dims is 4! Try expand dims to (1, 320, 320, 3)!
W inference: The dims of input(ndarray) shape (320, 320, 3) is wrong, expect dims is 4! Try expand dims to (1, 320, 320, 3)!
W inference: The dims of input(ndarray) shape (320, 320, 3) is wrong, expect dims is 4! Try expand dims to (1, 320, 320, 3)!
W inference: The dims of input(ndarray) shape (320, 320, 3) is wrong, expect dims is 4! Try expand dims to (1, 320, 320, 3)!
done
class: person, score: 0.8913032412528992
box coordinate topleft: (159.54501259326935, 145.2426918745041), bottomright: (177.8633736371994, 186.3882895708084)
class: person, score: 0.8837643265724182
box coordinate topleft: (82.14642906188965, 183.73637676239014), bottomright: (110.66749000549316, 226.49699115753174)
class: person, score: 0.8643947243690491
box coordinate topleft: (146.98097324371338, 140.67060202360153), bottomright: (164.14344692230225, 166.86144143342972)
class: person, score: 0.8264284729957581
box coordinate topleft: (110.99540531635284, 146.92019426822662), bottomright: (130.9836596250534, 177.2033714056015)
class: person, score: 0.7860860824584961
box coordinate topleft: (146.88146114349365, 127.81136840581894), bottomright: (163.5996789932251, 148.1453576683998)
class: person, score: 0.7520475387573242
box coordinate topleft: (170.8560609817505, 123.72485554218292), bottomright: (185.6856870651245, 143.04388225078583)
class: person, score: 0.6209931373596191
box coordinate topleft: (108.76676034927368, 133.68206477165222), bottomright: (119.2998595237732, 156.40799260139465)

成功后,可以看到 export 文件下多了 rknn 模型。

在这里插入图片描述

(五)部署测试模型(见下一篇博文)

【边缘设备】yolov5训练与rknn模型导出并在RK3588部署(亲测有效)二

附录信息

仓库 说明
https://github.com/rockchip-linux/rknpu2 RKNPU2 provides an advanced interface to access Rockchip NPU.
Support Platform
- RK3566/RK3568
- RK3588/RK3588S- RV1103/RV1106
Note: The rknn model must be generated using
RKNN Toolkit 2: https://github.com/rockchip-linux/rknn-toolkit2
https://github.com/rockchip-linux/rknn-toolkit2 RKNN-Toolkit2 is a software development kit for users to
perform model conversion, inference and performance evaluation on PC
and Rockchip NPU platforms (RK3566, RK3568, RK3588, RK3588S, RV1103, RV1106).
RKNN-Toolkit-Lite2 provides Python programming interfaces for Rockchip NPU platform
(RK3566, RK3568, RK3588, RK3588S) to help users deploy RKNN models and
accelerate the implementation of AI applications.

For the deployment of the RKNN model, please refer to:
https://github.com/rockchip-linux/rknpu2

For RK1808/RV1109/RV1126/RK3399Pro, please use:
https://github.com/rockchip-linux/rknn-toolkit
https://github.com/rockchip-linux/rknpu
https://github.com/airockchip/RK3399Pro_npuNOTES:
- Currently rknn-toolkit2 is not compatible with rknn-toolkit
- Currently only support on Ubuntu 18.04 python 3.6 / Ubuntu 20.04 python 3.8
- Latest version:1.4.0(Release version)
平台 仓库
RK3566/RK3568/RK3588/RK3588S/RV1103/RV1106 https://github.com/rockchip-linux/rknn-toolkit2
https://github.com/rockchip-linux/rknpu2
RK1808/RK1806/RV1109/RV1126 https://github.com/rockchip-linux/rknn-toolkit
https://github.com/rockchip-linux/rknpu
RK3399Pro https://github.com/rockchip-linux/rknn-toolkit
https://github.com/airockchip/RK3399Pro_npu

规格书

3588 Datasheet

在这里插入图片描述

在这里插入图片描述

参考(以下为编撰本文的引用参考)

  1. yolov5训练pt模型并转换为rknn模型,部署在RK3588开发板上——从训练到部署全过程
  2. RK3588模型推理总结
  3. NPU使用
  4. 一步一步教大家使用RK3588的NPU之在电脑端交叉编译yolov5运行在ARM平台上-哔哩哔哩
  5. 转换yolov5s.onnx为rknn模型RK3588主板实时推理和电脑端模拟推理-哔哩哔哩
  6. 摆脱电脑,直接在RK3588平台上推理,帮用户部署 RKNN 模加速 AI 应用的落地-哔哩哔哩
  7. 仓库下载 参考 rknn-toolkit 教程, 需要切换到 commit ID c5360f6e7009eb4d05f14d1cc9dae0963e949213, 可以直接在 官网github下载, 然后终端执行 git checkout c5360f6e7

RK3588 平台一直无法读取视频

问题描述:
我这边用的是 rk3588 的核心板,刷的固件里面有 opencv 4.5.5, 系统是 ubuntu 20.04 LTS 版本, 使用 cv::VideoCapture 无法读取 mp4 或其他视频,每次读取后 isOpened() 都是 false;
硬件是 rk3588 对应的开发板
以下编译安装直接在开发板上进行,不是在宿主机用交叉编译链编译安装的。

opencv 安装

下载 opencv4.5.5.zip, 解压后,在源代码目录新建 build 目录,进入 build 目录;

确保安装了相关依赖
确保安装了相关依赖
确保安装了相关依赖

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev liblapacke-dev
sudo apt-get install libxvidcore-dev libx264-dev
sudo apt-get install libatlas-base-dev gfortran 
sudo apt-get install -f ffmpeg   # show video

如果 libjasper 安装失败,请往下翻

cd opencv4.5.5
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=~/install/opencv4.5.5 -DBUILD_IPP_IW=OFF -DBUILD_WITH_DYNAMIC_IPP=OFF -DBUILD_JPEG=ON -DBUILD_PNG=ON -DBUILD_TIFF=ON -DBUILD_ZLIB=ON -DBUILD_SHARED_LIBS=ON -DBUILD_opencv_java_bindings_generator=OFF -DBUILD_opencv_python_bindings_generator=OFF -DWITH_MATLAB=OFF -DWITH_LAPACK=OFF -DWITH_FFMPEG=ON     -DWITH_TBB=ON -DWITH_V4L=ON -DWITH_GTK=ON -DWITH_OPENGL=ON -DWITH_IPP=OFF ..
make -j$(nproc)
make install

或者新建一个一键编译安装的脚本

build_ubuntu2004_arm64_opencv4.5.5.sh

#!/usr/bin/bash

# ###############################################
# # 确保安装了相关依赖
# sudo apt-get update
# sudo apt-get upgrade
# sudo apt-get install build-essential
# sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
# sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
# sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev liblapacke-dev
# sudo apt-get install libxvidcore-dev libx264-dev
# sudo apt-get install libatlas-base-dev gfortran 
# sudo apt-get install -f ffmpeg   # show video
# ###################################################

# opencv4.5.5
SRC_NAME_VER=opencv4.5.5

# 压缩包
SRC_ZIP=~/depends/${SRC_NAME_VER}.zip

# 源码和编译目录
SRC_DIR=~/depends/${SRC_NAME_VER}
BUILD_DIR=${SRC_DIR}/build

# 安装目录
INSTALL_ROOT=~/install
INSTALL_DIR=${INSTALL_ROOT}/${SRC_NAME_VER}


# 清空源码目录、编译目录以及对应的安装目录
rm -rf ${BUILD_DIR}
rm -rf ${SRC_DIR}
rm -rf ${INSTALL_DIR}

# 新建源码目录,编译目录和安装目录
mkdir -p ${SRC_DIR}
mkdir -p ${BUILD_DIR}
mkdir -p ${INSTALL_DIR}

# 解压安装包
unzip -d $SRC_DIR $SRC_ZIP

# 进入对应目录进行编译
pushd ${BUILD_DIR}

cmake -DCMAKE_BUILD_TYPE=RELEASE \
	-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
	-DBUILD_IPP_IW=OFF \
	-DBUILD_WITH_DYNAMIC_IPP=OFF \
	-DBUILD_JPEG=ON \
	-DBUILD_PNG=ON \
	-DBUILD_TIFF=ON \
	-DBUILD_ZLIB=ON \
	-DBUILD_SHARED_LIBS=ON \
	-DBUILD_JAVA=OFF \
	-DBUILD_opencv_java_bindings_generator=OFF \
	-DBUILD_opencv_python_bindings_generator=OFF \
	-DBUILD_opencv_python3=OFF \
	-DBUILD_opencv_python_tests=OFF \
	-DWITH_MATLAB=OFF \
	-DWITH_LAPACK=OFF \
	-DWITH_FFMPEG=ON \
	-DFFMPEG_DIR=/usr/local/ffmpeg \
	-DWITH_GSTREAMER=ON \
	-DWITH_TBB=ON \
	-DWITH_V4L=ON \
	-DWITH_GTK=ON \
	-DWITH_OPENCL=ON \
	-DWITH_OPENGL=ON \
	-DWITH_IPP=OFF ..

make -j$(nproc)
make install
popd

安装 libjasper 或许确认这个就可以了

大意了,一开始安装的时候,没有太在意这个库,所以一直重新编都没有管这个库
所以在安装 opencv 的时候一定要按照步骤来,否则要找很久的问题。
如果上述 opencv 重新编译安装还是出现无法读取视频的问题,请确保每个依赖库都已经成功安装
我相信很多人还是无法读取视频,那么就确认这个库吧。

sudo apt install libjasper1 libjasper-dev

执行上述命令会报错。那怎么办呢?修改 /etc/apt/source.list

sudo cp /etc/apt/source.list /etc/apt/source.list.bak
sudo gedit /etc/apt/source.list
deb http://mirrors.aliyun.com/ubuntu-ports/ focal main restricted
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-updates main restricted
deb http://mirrors.aliyun.com/ubuntu-ports/ focal universe
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-updates universe
deb http://mirrors.aliyun.com/ubuntu-ports/ focal multiverse
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-updates multiverse
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-security main restricted
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-security universe
deb http://mirrors.aliyun.com/ubuntu-ports/ focal-security multiverse
# 新增
deb http://ports.ubuntu.com/ubuntu-ports xenial-security main  

sudo apt update
sudo apt upgrade
sudo apt install libjasper1 libjasper-dev

NOTE: 以下过程是试错过程,不一定是必要过程,如果上述过程能解决问题,下面就不用管了。

ffmpeg 重新安装

这里为什么要重新安装 ffmpeg ? 翻阅了很多博客,说要重新安装 ffmpeg.

但是这里也不一定需要重新安装,重新安装肯定没问题。ffmpeg 版本不要安装太高,因为接口变换较大,可能 opencv 4.5.5 不兼容,我这里试过好几个版本( ffmpeg 6.0, ffmpeg 5.0.3, ffmpeg 4.4.4),在重新编译opencv时都编译失败。 ffmpeg 4.2.9 可以成功。

Download FFmpeg
ffmpeg-4.2.9

./configure --enable-shared --prefix=/usr/local/ffmpeg
make -j4
sudo make install
INSTALL	libavdevice/libavdevice.a
INSTALL	libavdevice/libavdevice.so
STRIP	install-libavdevice-shared
INSTALL	libavfilter/libavfilter.a
INSTALL	libavfilter/libavfilter.so
STRIP	install-libavfilter-shared
INSTALL	libavformat/libavformat.a
INSTALL	libavformat/libavformat.so
STRIP	install-libavformat-shared
INSTALL	libavcodec/libavcodec.a
INSTALL	libavcodec/libavcodec.so
STRIP	install-libavcodec-shared
INSTALL	libswresample/libswresample.a
INSTALL	libswresample/libswresample.so
STRIP	install-libswresample-shared
INSTALL	libswscale/libswscale.a
INSTALL	libswscale/libswscale.so
STRIP	install-libswscale-shared
INSTALL	libavutil/libavutil.a
INSTALL	libavutil/libavutil.so
STRIP	install-libavutil-shared
INSTALL	doc/ffmpeg.1
INSTALL	doc/ffplay.1
INSTALL	doc/ffprobe.1
INSTALL	doc/ffmpeg-all.1
INSTALL	doc/ffplay-all.1
INSTALL	doc/ffprobe-all.1
INSTALL	doc/ffmpeg-utils.1
INSTALL	doc/ffmpeg-scaler.1
INSTALL	doc/ffmpeg-resampler.1
INSTALL	doc/ffmpeg-codecs.1
INSTALL	doc/ffmpeg-bitstream-filters.1
INSTALL	doc/ffmpeg-formats.1
INSTALL	doc/ffmpeg-protocols.1
INSTALL	doc/ffmpeg-devices.1
INSTALL	doc/ffmpeg-filters.1
INSTALL	doc/libavutil.3
INSTALL	doc/libswscale.3
INSTALL	doc/libswresample.3
INSTALL	doc/libavcodec.3
INSTALL	doc/libavformat.3
INSTALL	doc/libavdevice.3
INSTALL	doc/libavfilter.3
INSTALL	doc/ffmpeg.1
INSTALL	doc/ffplay.1
INSTALL	doc/ffprobe.1
INSTALL	doc/ffmpeg-all.1
INSTALL	doc/ffplay-all.1
INSTALL	doc/ffprobe-all.1
INSTALL	doc/ffmpeg-utils.1
INSTALL	doc/ffmpeg-scaler.1
INSTALL	doc/ffmpeg-resampler.1
INSTALL	doc/ffmpeg-codecs.1
INSTALL	doc/ffmpeg-bitstream-filters.1
INSTALL	doc/ffmpeg-formats.1
INSTALL	doc/ffmpeg-protocols.1
INSTALL	doc/ffmpeg-devices.1
INSTALL	doc/ffmpeg-filters.1
INSTALL	doc/libavutil.3
INSTALL	doc/libswscale.3
INSTALL	doc/libswresample.3
INSTALL	doc/libavcodec.3
INSTALL	doc/libavformat.3
INSTALL	doc/libavdevice.3
INSTALL	doc/libavfilter.3
INSTALL	install-progs-yes
INSTALL	ffmpeg
INSTALL	ffplay
INSTALL	ffprobe
INSTALL	presets/libvpx-1080p50_60.ffpreset
INSTALL	presets/libvpx-360p.ffpreset
INSTALL	presets/libvpx-1080p.ffpreset
INSTALL	presets/libvpx-720p50_60.ffpreset
INSTALL	presets/libvpx-720p.ffpreset
INSTALL	doc/ffprobe.xsd
INSTALL	doc/examples/transcoding.c
INSTALL	doc/examples/vaapi_transcode.c
INSTALL	doc/examples/demuxing_decoding.c
INSTALL	doc/examples/filtering_video.c
INSTALL	doc/examples/muxing.c
INSTALL	doc/examples/avio_dir_cmd.c
INSTALL	doc/examples/extract_mvs.c
INSTALL	doc/examples/encode_audio.c
INSTALL	doc/examples/hw_decode.c
INSTALL	doc/examples/filter_audio.c
INSTALL	doc/examples/resampling_audio.c
INSTALL	doc/examples/decode_video.c
INSTALL	doc/examples/metadata.c
INSTALL	doc/examples/remuxing.c
INSTALL	doc/examples/filtering_audio.c
INSTALL	doc/examples/http_multiclient.c
INSTALL	doc/examples/avio_reading.c
INSTALL	doc/examples/qsvdec.c
INSTALL	doc/examples/vaapi_encode.c
INSTALL	doc/examples/decode_audio.c
INSTALL	doc/examples/transcode_aac.c
INSTALL	doc/examples/encode_video.c
INSTALL	doc/examples/scaling_video.c
INSTALL	doc/examples/README
INSTALL	doc/examples/Makefile
INSTALL	doc/examples/transcoding.c
INSTALL	doc/examples/vaapi_transcode.c
INSTALL	doc/examples/demuxing_decoding.c
INSTALL	doc/examples/filtering_video.c
INSTALL	doc/examples/muxing.c
INSTALL	doc/examples/avio_dir_cmd.c
INSTALL	doc/examples/extract_mvs.c
INSTALL	doc/examples/encode_audio.c
INSTALL	doc/examples/hw_decode.c
INSTALL	doc/examples/filter_audio.c
INSTALL	doc/examples/resampling_audio.c
INSTALL	doc/examples/decode_video.c
INSTALL	doc/examples/metadata.c
INSTALL	doc/examples/remuxing.c
INSTALL	doc/examples/filtering_audio.c
INSTALL	doc/examples/http_multiclient.c
INSTALL	doc/examples/avio_reading.c
INSTALL	doc/examples/qsvdec.c
INSTALL	doc/examples/vaapi_encode.c
INSTALL	doc/examples/decode_audio.c
INSTALL	doc/examples/transcode_aac.c
INSTALL	doc/examples/encode_video.c
INSTALL	doc/examples/scaling_video.c
INSTALL	doc/examples/README
INSTALL	doc/examples/Makefile
INSTALL	libavdevice/avdevice.h
INSTALL	libavdevice/version.h
INSTALL	libavdevice/libavdevice.pc
INSTALL	libavfilter/avfilter.h
INSTALL	libavfilter/buffersink.h
INSTALL	libavfilter/buffersrc.h
INSTALL	libavfilter/version.h
INSTALL	libavfilter/libavfilter.pc
INSTALL	libavformat/avformat.h
INSTALL	libavformat/avio.h
INSTALL	libavformat/version.h
INSTALL	libavformat/libavformat.pc
INSTALL	libavcodec/ac3_parser.h
INSTALL	libavcodec/adts_parser.h
INSTALL	libavcodec/avcodec.h
INSTALL	libavcodec/avdct.h
INSTALL	libavcodec/avfft.h
INSTALL	libavcodec/d3d11va.h
INSTALL	libavcodec/dirac.h
INSTALL	libavcodec/dv_profile.h
INSTALL	libavcodec/dxva2.h
INSTALL	libavcodec/jni.h
INSTALL	libavcodec/mediacodec.h
INSTALL	libavcodec/qsv.h
INSTALL	libavcodec/vaapi.h
INSTALL	libavcodec/vdpau.h
INSTALL	libavcodec/version.h
INSTALL	libavcodec/videotoolbox.h
INSTALL	libavcodec/vorbis_parser.h
INSTALL	libavcodec/xvmc.h
INSTALL	libavcodec/libavcodec.pc
INSTALL	libswresample/swresample.h
INSTALL	libswresample/version.h
INSTALL	libswresample/libswresample.pc
INSTALL	libswscale/swscale.h
INSTALL	libswscale/version.h
INSTALL	libswscale/libswscale.pc
INSTALL	libavutil/adler32.h
INSTALL	libavutil/aes.h
INSTALL	libavutil/aes_ctr.h
INSTALL	libavutil/attributes.h
INSTALL	libavutil/audio_fifo.h
INSTALL	libavutil/avassert.h
INSTALL	libavutil/avstring.h
INSTALL	libavutil/avutil.h
INSTALL	libavutil/base64.h
INSTALL	libavutil/blowfish.h
INSTALL	libavutil/bprint.h
INSTALL	libavutil/bswap.h
INSTALL	libavutil/buffer.h
INSTALL	libavutil/cast5.h
INSTALL	libavutil/camellia.h
INSTALL	libavutil/channel_layout.h
INSTALL	libavutil/common.h
INSTALL	libavutil/cpu.h
INSTALL	libavutil/crc.h
INSTALL	libavutil/des.h
INSTALL	libavutil/dict.h
INSTALL	libavutil/display.h
INSTALL	libavutil/downmix_info.h
INSTALL	libavutil/encryption_info.h
INSTALL	libavutil/error.h
INSTALL	libavutil/eval.h
INSTALL	libavutil/fifo.h
INSTALL	libavutil/file.h
INSTALL	libavutil/frame.h
INSTALL	libavutil/hash.h
INSTALL	libavutil/hdr_dynamic_metadata.h
INSTALL	libavutil/hmac.h
INSTALL	libavutil/hwcontext.h
INSTALL	libavutil/hwcontext_cuda.h
INSTALL	libavutil/hwcontext_d3d11va.h
INSTALL	libavutil/hwcontext_drm.h
INSTALL	libavutil/hwcontext_dxva2.h
INSTALL	libavutil/hwcontext_qsv.h
INSTALL	libavutil/hwcontext_mediacodec.h
INSTALL	libavutil/hwcontext_vaapi.h
INSTALL	libavutil/hwcontext_videotoolbox.h
INSTALL	libavutil/hwcontext_vdpau.h
INSTALL	libavutil/imgutils.h
INSTALL	libavutil/intfloat.h
INSTALL	libavutil/intreadwrite.h
INSTALL	libavutil/lfg.h
INSTALL	libavutil/log.h
INSTALL	libavutil/macros.h
INSTALL	libavutil/mathematics.h
INSTALL	libavutil/mastering_display_metadata.h
INSTALL	libavutil/md5.h
INSTALL	libavutil/mem.h
INSTALL	libavutil/motion_vector.h
INSTALL	libavutil/murmur3.h
INSTALL	libavutil/opt.h
INSTALL	libavutil/parseutils.h
INSTALL	libavutil/pixdesc.h
INSTALL	libavutil/pixelutils.h
INSTALL	libavutil/pixfmt.h
INSTALL	libavutil/random_seed.h
INSTALL	libavutil/rc4.h
INSTALL	libavutil/rational.h
INSTALL	libavutil/replaygain.h
INSTALL	libavutil/ripemd.h
INSTALL	libavutil/samplefmt.h
INSTALL	libavutil/sha.h
INSTALL	libavutil/sha512.h
INSTALL	libavutil/spherical.h
INSTALL	libavutil/stereo3d.h
INSTALL	libavutil/threadmessage.h
INSTALL	libavutil/time.h
INSTALL	libavutil/timecode.h
INSTALL	libavutil/timestamp.h
INSTALL	libavutil/tree.h
INSTALL	libavutil/twofish.h
INSTALL	libavutil/version.h
INSTALL	libavutil/xtea.h
INSTALL	libavutil/tea.h
INSTALL	libavutil/tx.h
INSTALL	libavutil/lzo.h
INSTALL	libavutil/avconfig.h
INSTALL	libavutil/ffversion.h
INSTALL	libavutil/libavutil.pc

编译安装完成后,在 /usr/local/ffmpeg 下新建 ffmpeg-config.cmake, 文件内容如下:

ffmpeg-config.cmake

set(ffmpeg_path "${CMAKE_CURRENT_LIST_DIR}")

message("ffmpeg_path: ${ffmpeg_path}")

set(FFMPEG_EXEC_DIR "${ffmpeg_path}/bin")
set(FFMPEG_LIBDIR "${ffmpeg_path}/lib")
set(FFMPEG_INCLUDE_DIRS "${ffmpeg_path}/include")

# library names
set(FFMPEG_LIBRARIES
    ${FFMPEG_LIBDIR}/libavformat.so
    ${FFMPEG_LIBDIR}/libavdevice.so
    ${FFMPEG_LIBDIR}/libavcodec.so
    ${FFMPEG_LIBDIR}/libavutil.so
    ${FFMPEG_LIBDIR}/libswscale.so
    ${FFMPEG_LIBDIR}/libswresample.so
    ${FFMPEG_LIBDIR}/libavfilter.so
)

# found status
set(FFMPEG_libavformat_FOUND TRUE)
set(FFMPEG_libavdevice_FOUND TRUE)
set(FFMPEG_libavcodec_FOUND TRUE)
set(FFMPEG_libavutil_FOUND TRUE)
set(FFMPEG_libswscale_FOUND TRUE)
set(FFMPEG_libswresample_FOUND TRUE)
set(FFMPEG_libavfilter_FOUND TRUE)

# library versions, 注意这几个变量,一定要设置为全局CACHE变量
set(FFMPEG_libavutil_VERSION 56.31.100 CACHE INTERNAL "FFMPEG_libavutil_VERSION") # info
set(FFMPEG_libavcodec_VERSION 58.54.100 CACHE INTERNAL "FFMPEG_libavcodec_VERSION") # info
set(FFMPEG_libavformat_VERSION 58.29.100 CACHE INTERNAL "FFMPEG_libavformat_VERSION") # info
set(FFMPEG_libavdevice_VERSION 58.8.100 CACHE INTERNAL "FFMPEG_libavdevice_VERSION") # info
set(FFMPEG_libavfilter_VERSION 7.57.100 CACHE INTERNAL "FFMPEG_libavfilter_VERSION") # info
set(FFMPEG_libswscale_VERSION 5.5.100 CACHE INTERNAL "FFMPEG_libswscale_VERSION") # info
set(FFMPEG_libswresample_VERSION 3.5.100 CACHE INTERNAL "FFMPEG_libswresample_VERSION") # info

set(FFMPEG_FOUND TRUE)
set(FFMPEG_LIBS ${FFMPEG_LIBRARIES})

status("    #################################### FFMPEG:"       FFMPEG_FOUND         THEN "YES (find_package)"                       ELSE "NO (find_package)")
status("      avcodec:"      FFMPEG_libavcodec_VERSION    THEN "YES (${FFMPEG_libavcodec_VERSION})"    ELSE NO)
status("      avformat:"     FFMPEG_libavformat_VERSION   THEN "YES (${FFMPEG_libavformat_VERSION})"   ELSE NO)
status("      avutil:"       FFMPEG_libavutil_VERSION     THEN "YES (${FFMPEG_libavutil_VERSION})"     ELSE NO)
status("      swscale:"      FFMPEG_libswscale_VERSION    THEN "YES (${FFMPEG_libswscale_VERSION})"    ELSE NO)
status("      avresample:"   FFMPEG_libavresample_VERSION THEN "YES (${FFMPEG_libavresample_VERSION})" ELSE NO)

卸载原装 opencv

以上还不能解决问题的话,删除所有 opencv 的安装,全部重装。

安装顺序如下:

  1. 依赖库 ( sudo apt install xxx )
  2. ffmpeg 源码编译安装
  3. 重新编译安装 opencv

参考

debug-ubuntu下opencv无法读取视频且capture.isOpened()测试一直为false-可参考
🤓opencv+ffmpeg编译打包全解指南-可参考
【环境配置】Windows 11 的 WSL(Ubuntu2204) 安装OpenCV 4.5.4 (亲测有效)
linux下 opencv 和 ffmpeg安装
RK3588移植-opencv交叉编译aarch64
瑞芯微-交叉编译环境搭建-opencv环境搭建(基于RV1109-1126)-(基于ubuntu18.04)
RK3588编译Opencv最新版
树莓派4B(aarch64,arm64)bullseye无法定位libjasper-dev

GIT常用命令

配置

  1. 配置操作人员名称

    git config --global user.name "xxx"

  2. 配置操作人员邮箱

    git config --global user.email "xxx@example.com"

  3. 配置信息显示方式

    git config --global color.ui true

本地操作

  1. 初始化git仓库

    git init . # 在当前目录下创建一个.git文件夹,以后所有的操作都会被记录在里面

  2. 添加更改到索引库

    git add .

  3. 将索引信息提交到仓库

    git commit -m "the first time commit here"

  4. 查看最近一次的更改日志

    git log -l # 如果想着最近3次,可以改成3

  5. 将分支branch1合并到当前分支上,如果冲突,就会提示,按照提示修改即可

    git merge branch1

  6. 建立新的分支 newbranch

    git branch newbranch

  7. 列出所有分支

    git branch

  8. 签出分支newbranch

    git checkout newbranch

  9. 创建并签出分支branch0

    git checkout -b branch0

  10. 临时保存当前工作

    git stash

  11. 列出所有临时保存的工作

    git stash list

  12. 恢复某一个临时工作

    git stash pop stash@{2}

  13. 创建里程碑1.0.0

    git tag 1.0.0

  14. 将里程碑1.0.0相关的文件打包起来发布

    git archive --format=zip 1.0.0 > code1.0.0.zip

  15. 返回历史的操作reset

    git reset HEAD^ # 返回到前一次没有add的状态
    git reset --soft HEAD^ # 返回前一次没有commit的状态
    git reset --hard HEAD^ # 返回前一个状态,工作区的修改也会被同时撤销
    HEAD^ # 前一次提交
    HEAD^^ # 前两次提交
    HEAD^^^ # 前三次提交
    SHA1_HASH #每次提交都对应着一个唯一的 SHA1_HASH 值。一般情况下只需输入前 5 项即 可 注:如果你担心 reset 后会后悔,那么在 reset 前记录一下最新一次提交的 SHA1_HASH 值。

  16. 回到历史中某个时候并新增一条分支newbranch

    git checkout SHA1_HASH && git branch newbranch

远程操作

  1. 建立空远程仓库

    git init --bare

  2. 将远程仓库地址用origin来命名

    git remote add origin coder@192.168.0.222:xxxx

  3. 拷贝一份远程仓库

    git clone origin

  4. 在本地创建一个分支branch1,并将远程库中的master分支拷贝到本地的branch1分支上

    git fetch origin master:branch1

  5. 将远程库中的master分支拷贝到本地的branch2分支上并进行合并,如果冲突则解决

    git pull origin master:branch2

  6. 将本地的branch3分支推送到远程库中的branch4分支中

    git push origin branch3:branch4

  7. 删除远程库的branch4分支

    git push origin :branch4

  8. 将本地的branch5分支推送到远程库中

    git push origin branch5

  9. 将本地所有分支推送到远程库中

    git push origin --all

【问题】

Git是应用极其广泛的代码版本管理工具。在编写代码的过程中会遇到很多问题,之前遇到过团队成员在提交代码仓库时,提交了大量的图片和视频文件以及一些编译的临时文件,导致代码仓库非常大,每次其他成员拉取的时候都要拉取一堆垃圾信息。那么如何避免该问题呢?

【解决办法】

在新建仓库的时候,建立一个 .gitignore 文件,该文件可以忽略掉那些临时文件,或者不需要跟踪的文件,也可以忽略掉一些文件夹。那么 .gitignore 的规则如何呢?

  1. .gitignore 文件的存放
    该文件可以存放在仓库的根目录下,它递归应用于整个仓库中。也可以放在子目录中,子目录中的 .gitignore 作用域在其目录。
  2. .gitignore 格式规范
  • 所有空行或者以 # 开头的行都会被 Git 忽略;
  • 可以使用标准的 glob 模式匹配,它会递归应用到整个工作区;
  • 匹配模式可以以 / 开头防止递归;
  • 匹配模式可以以 / 结尾指定目录;
  • 要忽略那些指定格式的文件或目录,可以在模式前加上 ! 取反,即该类文件或目录继续进行跟踪。

glob 模式是指 shell 简化了正则表达式。* 匹配0个或多个任意字符,[abc] 匹配任意一个列在方括号中的字符(要么匹配 a, 要么匹配 b, 要么匹配 c )。? 只匹配一个任意字符。如果方括号中使用了短划线分割两个字符,如 [0-9] 会匹配 0~9 之间的数字;使用 ** 表示匹配任意中间目录,如 a/**/z 表示匹配 a/z, a/b/z, a/b/c/d/e/z

# 忽略所有的 .a 文件
*.a

# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a

# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO

# 忽略任何目录下名为 build 的文件夹
build/

# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
  1. 要养成一个好的习惯
    每次建立新仓库的时候,应及时建立 .gitignore 文件,以免将来提交无用的文件。

Git 除了利用 .gitignore 方式忽略不需要跟踪的文件外。还提供了另外一种方式 exclude, exclude 存放在 .git/info/exclude , 它与 .gitignore 不同的是, exclude 是本地需要排除的文件,不会提交到仓库中应用在别人机器上,而 .gitignore 本身可以提交到仓库中,适用于使用仓库的所有人。

.gitignore 文件可以作为占位文件,例如有些文件夹需要同步到仓库中,可以在文件夹中新建一个 .gitignore 文件,下次拉取的时候可以同步拉取了这个空目录。

  1. 如果已经提交了大文件到仓库中, 怎么办?
    思考中,下集再见

【示例】

.gitignore 模板文件

c++/cuda 项目下的 .gitignore 文件模板

# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

# cuda
*.i
*.ii
*.gpu
*.ptx
*.cubin
*.fatbin

c 项目下的 .gitignore 文件模板

# Prerequisites
*.d

# Object files
*.o
*.ko
*.obj
*.elf

# Linker output
*.ilk
*.map
*.exp

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Debug files
*.dSYM/
*.su
*.idb
*.pdb

# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

Python 项目下的 .gitignore 文件模板

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
#   in version control.
#   https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

【参考】

  1. https://www.cnblogs.com/pylemon/archive/2012/07/16/2593112.html
  2. https://github.com/github/gitignore
  3. https://blog.csdn.net/ThinkWon/article/details/101447866

【问题】

很多小明同学啊,在写代码的时候,一不小心将测试的cnn模型或者测试视频放到仓库目录下,同时忘记了编写 .gitignore 文件忽略对应文件,然后将所有文件推到了公司代码服务器上,该代码仓库就瞬间爆炸了,本来最多就几MB的代码库,一下子甚至飙升到了几个GB的大小。其他同学再拉取代码的时候要好几分钟,严重影响各位同学写代码了,同时占据了大量的硬盘空间和代码服务器空间。

【解决】

一共分三步:

  1. 找到对应的大文件和提交历史;
  2. 删除大文件和修改提交历史;
  3. 重新推送代码仓库。

第一步:找到大文件

命令

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"

输出

c9853e631785727a7679b2179be356c9f268a97c
b9d121ead2c499b77fdaa10fc59f95cf2a41ca46 8.mp4

第二步:删除大文件

命令

git filter-branch -f --prune-empty --index-filter "git rm -rf --cached --ignore-unmatch 8.mp4" --tag-name-filter cat -- --all

输出

WARNING: git-filter-branch has a glut of gotchas generating mangled history
         rewrites.  Hit Ctrl-C before proceeding to abort, then use an
         alternative filtering tool such as 'git filter-repo'
         (https://github.com/newren/git-filter-repo/) instead.  See the
         filter-branch manual page for more details; to squelch this warning,
         set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 463a9cb31ef1b6f0e67256b65c30a4ff9fb7d642 (3/7) (1 seconds passed, remaining 1 predicted)    rm '8.mp4'
Rewrite c9853e631785727a7679b2179be356c9f268a97c (3/7) (1 seconds passed, remaining 1 predicted)    rm '8.mp4'
Rewrite 2c1755a720639f55ebf93df5484b94b4b4380ef3 (3/7) (1 seconds passed, remaining 1 predicted)    rm '8.mp4'
Rewrite c30b0cb6bb4a6202d139a01a033255767ddd38ea (7/7) (2 seconds passed, remaining 0 predicted)
WARNING: Ref 'refs/heads/master' is unchanged
WARNING: Ref 'refs/heads/new' is unchanged
Ref 'refs/remotes/origin/master' was rewritten
WARNING: Ref 'refs/remotes/origin/new' is unchanged

第三步:推送仓库

命令

git push origin --force --all

输出

Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:enxun/testgit.git
 + c30b0cb...cdf4f61 master -> master (forced update)

另外

提交完成后,请其他各位同学删除本地仓库,重新从服务器拉取代码,不要再推送了,要不然又要重新搞一遍。

【扩展】

  1. Windows PowerShell 下执行有关命令会出现问题
    git verify-pack -v .git/objects/pack/pack-c1a9c4b28655a4a0353d0fa4149a8579fd53de34.idx | sort -k 3 -n | tail -3

还是用回 git bash 不要用 Windows PowerShell

切换到 git bash

  1. 双引号不是单引号
    git filter-branch -f --prune-empty --index-filter "git rm -rf --cached --ignore-unmatch 8.mp4" --tag-name-filter cat -- --all 命令里是"git rm -rf --cached --ignore-unmatch 8.mp4" 而不是 'git rm -rf --cached --ignore-unmatch 8.mp4',否则会出现fatal: bad revision 'git rm --ignore-unmatch --cached 8.mp4'提示。

  2. git-count-objects - 计算解包的对象数量及其磁盘消耗量

  3. git-gc - 清理不必要的文件并优化本地存储库

【参考】

  1. progit https://git-scm.com/book/en/v2 P460~P464
  2. https://harttle.land/2016/03/22/purge-large-files-in-gitrepo.html
  3. https://cloud.tencent.com/developer/section/1138773

Git 仓库中有时会不小心加入了一些大文件,例如模型文件,视频文件
模型文件有可能以 .weights 结尾,或者 .onnx 结尾等等
视频文件有可能以 .avi 结尾,或者 .mp4 结尾
大文件如果一直在仓库中,仓库体积会非常大,下面我们提供一个脚本,专门用于清理 仓库中的文件使用。

仓库清理脚本

本脚本旨在从指定的 Git 仓库中移除不必要的 .weights 文件,优化仓库,并将更改推送到远程服务器。它提供了用户交互、详细日志输出及错误处理功能,以实现顺畅且可靠的清理过程。

使用前准备

在使用本脚本之前,请确保满足以下条件:

  • 您拥有一个包含待移除 .weights 文件的 Git 仓库。
  • 已在系统上安装 Git

可选:为了提升性能,建议安装 git-filter-repo 工具(通常通过 pip install git-filter-repo 安装)。如果安装了 git-filter-repo,脚本将自动使用它替代 git filter-branch 命令进行更高效的历史清理。

使用方法

  1. 下载或复制脚本:将以下脚本保存为 clean_repo.sh 文件。

#!/bin/bash
# 清理指定仓库中无用的.weights文件
# 通过命令行参数接收仓库地址(文件夹路径)

# 获取仓库路径(优先使用命令行参数,否则使用当前目录)
if [ -n "$1" ]; then
    repository_path="$1"
else
    repository_path="."
fi

# 检查路径是否存在且为Git仓库
if [ ! -d "$repository_path" ] || ! (cd "$repository_path" && git rev-parse --is-inside-work-tree &>/dev/null); then
    echo "Error: The specified path '$repository_path' is not a valid Git repository."
    exit 1
fi

# 用户确认是否继续
read -p "Are you sure you want to proceed with cleaning the repository at '$repository_path'? [y/N] " confirm
confirm=${confirm,,}  # Convert to lowercase
if [[ $confirm != "y" ]]; then
    echo "Aborting the operation."
    exit 0
fi

cd "$repository_path" || exit 1  # 切换到指定仓库目录,若失败则退出脚本

# 清理垃圾文件并记录结果
echo "Cleaning up unnecessary .weights files..."
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.weights' --prune-empty --tag-name-filter cat -- --all || {
    echo "Error: Failed to clean up .weights files. Check the output above for details."
    exit 1
}

# 记录清理前后的仓库大小
before_size=$(du -sh .git | cut -f1)
echo "Repository size before cleanup: $before_size"

# 提交到远程仓库
echo "Pushing changes to remote repository (this may take some time)..."
git push origin --force --all || {
    echo "Error: Failed to push changes to the remote repository. Check your network connection and authentication settings."
    exit 1
}

# 回收垃圾并压缩本地仓库
echo "Performing garbage collection and compression..."
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

# 可选:进行更深度的压缩(视情况决定是否需要)
git gc --aggressive --prune=now

# 记录清理后的仓库大小
after_size=$(du -sh .git | cut -f1)
echo "Repository size after cleanup: $after_size"

echo "Cleanup completed successfully."

  1. 赋予执行权限:在终端中,使用 chmod +x clean_repo.sh 命令为脚本赋予执行权限。

  2. 执行脚本

    • 指定仓库路径:运行 ./clean_repo.sh /path/to/repository,其中 /path/to/repository 是您要清理的仓库路径。
    • 使用当前目录:如果您想清理当前目录下的仓库,只需运行 ./clean_repo.sh

    脚本将引导您完成确认、清理、推送、压缩等步骤,并在过程中输出详细日志。

注意事项

  • 谨慎操作:清理操作会修改仓库历史,可能导致分支合并复杂性增加。请确保所有团队成员知晓此次清理,并在执行前备份重要数据。
  • 权限要求:执行清理和推送操作需具有相应的 Git 权限。确保您有权修改所清理仓库的历史记录及向远程服务器推送更改。
  • 性能影响:对于大型仓库,清理和压缩过程可能耗时较长。请耐心等待,并确保网络连接稳定。
  • 清理效果:清理后,仓库在本地和远程的大小可能不会立即更新。请等待一段时间后刷新查看,或联系服务提供商确认是否需要手动触发更新。

@echo off
setlocal

REM 设置 Git 仓库根目录
set "rootDirectory=\path\to\git\folders"

REM 使用 for /r 循环遍历目录树
for /R "%rootDirectory%" %%i in (.) do (
    if exist "%%i\.git\" (
        echo Found Git repository in folder: %%i
        pushd "%%i"
        
        REM 判断当前是否为 PowerShell 环境,如果是则使用 PowerShell 执行命令
        powershell -Command "if ($Host.Name -eq 'ConsoleHost') { git pull origin HEAD; git submodule update --init --recursive } else { cmd /c 'git pull origin HEAD & git submodule update --init --recursive' }"

        popd
        echo Finished updating repository and submodules.
    )
)

echo All repositories have been updated.

endlocal

自动拉取目录下所有 git 项目的最新仓库

学习的时候会遇到下载很多代码仓库,但不一定记得每天都会拉取最新的仓库,为此设立一个自动拉取项目仓库代码的程序。

找到 git 项目,并拉取最新仓库

pull_all_gitproject.sh

#!/bin/bash

# 查找给定文件夹下的所有文件夹
# 通过参数传递需要查找仓库的目录, 方法1
find $1 -type d > all_folders.txt
# 可以做这里自己设置固定的,也可以通过参数进行设置,方法2 
#find /home/xx/open -type d > all_folders.txt

# 当前路径
cur_dir=$(pwd)

# 先将所有文件夹写入到一个临时文件 all_folders.txt 中
cat all_folders.txt | while read line
do
    # 根据末尾是否为 .git 判断是否为 git 仓库
    suffix="${line:0-4}"    
    if [ "${suffix}" == ".git" ]
    then
        # 取项目路径
        par_folder=${line%/*}

        # 切换到项目路径
        cd ${par_folder}
        echo "In folder: ${par_folder}" 
        echo "git pull origin to ${par_folder}"
        git remote -v
        git pull origin
        echo "..."
        echo "done!"
        echo ""

        # 返回脚本路径
        cd ${cur_dir}
    fi
done

手动执行脚本

# 内部设定了目录,方法2
bash pull_all_gitproject.sh

# 参数设定目录,方法1
bash pull_all_gitproject.sh /home/xx/open

自动定时脚本

crontab -u //设定特定用户的定时服务
crontab -l //列出当前用户定时服务内容
crontab -r //删除当前用户的定时服务
crontab -e //编辑当前用户的定时服务

设定一个每天 13:00 定时拉取 git 代码的定时任务

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

输入 crontab -e 进入到编辑环境;将以下代码写入

0 13 * * * /home/xx/pull_all_gitproject.sh /home/xx/open

xx 代表的电脑的用户名,自己替换;

crontab -l 查看定时任务

【参考】

定时脚本实例

0%