0%

动态追踪算法

算法地址:https://github.com/mikel-brostrom/Yolov7_StrongSORT_OSNet。

pip install -r requirements.txt

运行

项目下载好后,根据github的使用文档,可以在项目目录下执行:python track.py --source test.mp4 --strong-sort-weights osnet_x0_25_market1501.pt

如果执行 python track.py --source test.mp4 项目会自动去google网盘下载osnet模型,所以可以提前下载StrongSort模型模型下载区,然后用--strong-sort-weights指定即可

这里 source 可以是视频文件、摄像头 ID 或者网络视频(rtsp、http、https 都支持)

Yolo 模型

这个项目使用的Yolo算法,所以在里面的Yolo目录中可以像往常一样使用yolo算法生成自己的训练模型,最后在追踪算法内指定YOLO模型即可--yolo-weights yolov7.pt --img 640

StrongSort模型

模型可以到 https://kaiyangzhou.github.io/deep-person-reid/MODEL_ZOO 下载,这里的模型后缀是 pth,可以直接重命名为 pt

代码解析

打开track.py

从109行开始加载数据流,dataset为要识别的视频流

148行开始便利dataset视频流,将每一帧作为输入,im,im0s,im0都是视频的一帧,赋值给了curr_frames, prev_frames,当前帧和上一帧

162行pred = model(im),pred为帧图片识别结果

198行将当前帧图片和上一帧图片作为入参输入到strongSort内

利用算法

算法在:track.py 中,算法执行可以选择 --show-vid 从而开启一个识别视频流,同时后台会实时的打印识别到的物体

算法所有的入参可以在 track.py 第 287行中看到

算法在第248行打印识别结果,可以在这里将识别结果发送到kafka或者写入redis操作,从而配合其他系统使用

算法在171行开始处理图形识别

upload successful

Yolo算法

Yolo是一个非常棒的视觉识别算法,项目地址:https://github.com/ultralytics/yolov5

个人地址:/home/tr/Documents/JupyterNotebook/YOLOv5

在myTrain.ipynb中写了使用训练的demo

upload successful

文件目录介绍

upload successful

  1. data目录:存放训练数据集,数据标记,训练配置等(yaml文件)

  2. model 模型算法核心(不用关注)

  3. runs 每执行一次detect,或者训练都会在目录下生成新的结果目录

  4. weights 存放模型结果

标记图片工具-生成训练工具

1
2
docker pull heartexlabs/label-studio:latest\n
docker run -it -p 6002:8080 -v ~/Documents/LabelStudio/mydata:/label-studio/data heartexlabs/label-studio:latest label-studio --log-level DEBUG

docker 拉取完毕后访问6002端口即可,注册账户,上传图片进行标记,具体使用方法很简单,标记完毕后导出数据格式为yolo

upload successful

编写训练配置

在label-studio中标记好导出的数据有两个目录,images和labels,labels内每个txt文件对应各自的图片文件,第一列为物品类别,后面分别是方框的xy坐标

需要注意的是,第一列的类别标签一会要作为配置文件内的类别,不能弄混

假设导出的数据目录为:tr03(内有images和labels目录),放入YOLOV5/datasets内,创建文件:YOLOV5/yolov5/data/tr03.yaml,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/tr03 # dataset root dir
train: images/ # train images (relative to 'path') 128 images
val: images/ # val images (relative to 'path') 128 images
test: # test images (optional)


# Classes
names:
0: TR
1: person
2: chair

Yolo算法的训练

Yolo已经存在了一些训练好的模型,我们再次训练的时候,可以基于已有的模型,也可以自己从头训练

!python train.py --img 640 --batch 16 --epochs 600 --data tr03.yaml --weights ./weights/yolov5s.pt 这个命令就是基于 weights目录下的yolov5s.pt模型训练,训练600次

upload successful

执行完毕以后,会在runs目录下生成最新结果,我们的模型文件也在其中

upload successful

Yolo算法的使用

有了模型文件后可以利用模型识别各种图片

1
2
3
4
5
6
7
8
9
10
11
12
# YOLOv5 PyTorch HUB Inference (DetectionModels only)
import torch

# model = torch.hub.load('ultralytics/yolov5', 'yolov5s.pt') # yolov5n - yolov5x6 or custom
model = torch.hub.load('./','custom', './runs/train/exp8/weights/best.pt', source='local') # yolov5n - yolov5x6 or custom
# model = torch.hub.load('./','custom', './weights/yolov5s.pt', source='local') # yolov5n - yolov5x6 or custom
im = '../datasets/tr03/images/test.jpg' # file, Path, PIL.Image, OpenCV, nparray, list
results = model(im) # inference
results.print() # or .show(), .save(), .crop(), .pandas(), etc.

model('../datasets/tr02/images/train01/01.jpg').show()

upload successful

ESP8266

通常在购买完芯片后插上去看com口即可(linux下是/dev/ttyUSB0),如果链接电脑无设备识别,需要下载ch40的驱动:https://www.wch.cn/download/CH341SER_LINUX_ZIP.html

有windows和linux版本,这里我下载了linux版本,解压进入目录后执行make 如果提示缺少libguile-3.0.so,需要执行sudo pacman -S guile 更新最新的guile库,最后执行make load加载

orika

一、Orika背景介绍   

  Orika是java Bean映射框架,可以实现从一个对象递归拷贝数据至另一个对象。在开发多层应用程序中非常有用。在这些层之间交换数据时,通常为了适应不同API需要转换一个实例至另一个实例。

  有很多方法可以实现:硬代码拷贝或Dozer实现bean映射等。总之,需要简化不同层对象之间映射过程。

  Orika使用字节码生成器创建开销最小的快速映射,比其他基于反射方式实现(如,Dozer)更快。之前使用Bean Copy 性能非常慢,发现在这个领域业界还是有很多新秀的。 Orika 应该就算一个比较好的吧。

二、优势

  1. 性能
      大概是Dozer的8-10 倍, 这个上面的已经做了描述

  2. 内存消耗
      大概是Dozer内存消耗的一半多点。 为什么做到这点的还没想清楚, 估计是因为运行期不需要维护复杂的Mapping 关系。 不需要大量的Mapping 关系查找以及需要的对这些查找优化所消耗的空间。

  3. 简单
      Orika的代码短小精悍, 而且可读性非常强, Dozer如果要加减一个功能, 不才完全没有信心, Orika 我还是可以偶尔在Orika里面打几个酱油的。

三、基础使用

Maven项目依赖包:POM文件直接依赖进去即可。

1
2
3
4
5
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.4.6</version>
</dependency>

创建两个Bean对象,用于复制使用。   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// UserVo对象
@Data //Set GET方法
@Accessors(chain = true)
public class UserVo {
private String id;
private String name;
}
// User对象

@Data
@Accessors(chain = true)
public class User {
private String id;
private String name;
}
使用场景(如果对象中属性太多,普通逻辑处理代码太多)
A对象复制到B对象(对象复制)
//业务场景,将A对象复制B对象中
//1.普通逻辑处理
User A = new User().setId("123").setName("1231");
UserVo B = new UserVo().setId(A.getId()).setName(A.getName());
System.out.println("普通方式将A对象复制B对象中:"+B);

//使用orika复制工具将A复制到B对象中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
UserVo map = mapperFactory.getMapperFacade().map(A, UserVo.class);
System.out.println("orika复制对象:"+map);
由上得出控制台输出如下:
普通方式将A对象复制B对象中:UserVo(id=123, name=1231)

orika复制对象:UserVo(id=123, name=1231)

2.A集合复制到B集合(集合复制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//1.普通逻辑处
//A对象
List<User> A = Arrays.asList(new User().setId("123").setName("张三"));
//B对象
List<UserVo> B = new ArrayList<>();
//将A集合数据复制到B集合中
A.forEach(x->{
B.add( new UserVo().setId(x.getId()).setName(x.getName()));
});
System.out.println("将A集合中数据set到B集合中数据打印");

//使用orika复制工具将A集合复制到B集合中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
List<UserVo> userVo = mapperFactory.getMapperFacade().mapAsList
mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
System.out.println("orika直接复制对象集合打印结果:"+userVo);
由上得出控制台输出如下:
`将A集合中数据set到B集合中数据打印:[UserVo(id=123, name=张三)]`

`orika直接复制对象集合打印结果:[UserVo(id=123, name=张三)]`
到此为止您已经算入门了,以上是Orika的基础使用,由此发现如果对象中属性如果20个,那么用普通的逻辑处理需要20个set过去,如果用Orika两行代码搞定。话不多说关键步骤总结一波(关键必须牢记):
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.getMapperFacade().map(操作对象)
mapperFactory.getMapperFacade().mapAsList(操作集合对象)

四、高级使用方法

创建两个Bean对象,用于复制使用。
   UserVo对象

1
2
3
4
5
6
7
@Data //Set GET方法
@Accessors(chain = true)
public class UserVo {
private String id;
private String userName;
private int ageOne;
}

  User对象

1
2
3
4
5
6
7
@Data
@Accessors(chain = true)
public class User {
private String id;
private String name;
private int age;
}

使用场景(对象A与对象B中属性不一致时,如果对象中属性太多,普通逻辑处理代码太多)
  1.A对象复制到B对象,对象中属性不一样时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//业务场景,将A对象复制B对象中,A对象中的字段与B对象中的字段不一致
//1.普通逻辑处理
User A = new User().setId("123").setName("张三").setAge(20);
UserVo B = new UserVo().setId(A.getId()).setUserName(A.getName()).setAgeOne(A.getAge());
System.out.println("普通方式将A对象处理B对象中:"+B);.

//使用orika复制工具将A复制到B对象中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
UserVo userVo = mapperFactory.getMapperFacade().map(A, UserVo.class);
System.out.println("orika复制对象:"+userVo);
由上得出控制台输出如下:
`普通方式将A对象处理B对象中:UserVo(id=123, userName=张三, ageOne=20)`

`orika复制对象:UserVo(id=123, userName=张三, ageOne=20)`

2.A集合对象复制到B集合对象,对象中属性不一样时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//1.普通逻辑处里A对象中与B对象字段不一致处理
//A对象
List<User> A = Arrays.asList(new User().setId("123").setName("张三").setAge(20));
//B对象
List<UserVo> B = new ArrayList<>();
//将A集合数据复制到B集合中
A.forEach(x->{
B.add(new UserVo().setId(x.getId()).setUserName(x.getName()).setAgeOne(x.getAge()));
});
System.out.println("将A集合中数据set到B集合中数据打印"+B);

//使用orika复制工具将A集合复制到B集合中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
System.out.println("orika复制对象:"+userVos);
由上得出控制台输出如下:
`将A集合中数据set到B集合中数据打印[UserVo(id=123, userName=张三, ageOne=20)]`

`orika复制对象:[UserVo(id=123, userName=张三, ageOne=20)]`
话不多说关键步骤总结一波(关键必须牢记):
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
//集合复制--使用mapAsList
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
//对象复制--使用map
UserVo userVos = mapperFactory.getMapperFacade().map(A, UserVo.class);

五、总结工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* 映射工具类
*/
public enum MapperUtils {

INSTANCE;

/**
* 默认字段工厂
*/
private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build();

/**
* 默认字段实例
*/
private static final MapperFacade MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade();

/**
* 默认字段实例集合
*/
private static Map<String, MapperFacade> CACHE_MAPPER_FACADE_MAP = new ConcurrentHashMap<>();

/**
* 映射实体(默认字段)
*
* @param toClass 映射类对象
* @param data 数据(对象)
* @return 映射类对象
*/
public <E, T> E map(Class<E> toClass, T data) {
return MAPPER_FACADE.map(data, toClass);
}

/**
* 映射实体(自定义配置)
*
* @param toClass 映射类对象
* @param data 数据(对象)
* @param configMap 自定义配置
* @return 映射类对象
*/
public <E, T> E map(Class<E> toClass, T data, Map<String, String> configMap) {
MapperFacade mapperFacade = this.getMapperFacade(toClass, data.getClass(), configMap);
return mapperFacade.map(data, toClass);
}

/**
* 映射集合(默认字段)
*
* @param toClass 映射类对象
* @param data 数据(集合)
* @return 映射类对象
*/
public <E, T> List<E> mapAsList(Class<E> toClass, Collection<T> data) {
return MAPPER_FACADE.mapAsList(data, toClass);
}


/**
* 映射集合(自定义配置)
*
* @param toClass 映射类
* @param data 数据(集合)
* @param configMap 自定义配置
* @return 映射类对象
*/
/* public <E, T> List<E> mapAsList(Class<E> toClass, Collection<T> data, Map<String, String> configMap) {
T t = data.stream().findFirst().orElseThrow(() -> new ResourceNotExistException("映射集合,数据集合为空"));
MapperFacade mapperFacade = this.getMapperFacade(toClass, t.getClass(), configMap);
return mapperFacade.mapAsList(data, toClass);
}*/

/**
* 获取自定义映射
*
* @param toClass 映射类
* @param dataClass 数据映射类
* @param configMap 自定义配置
* @return 映射类对象
*/
private <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap) {
String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName();
MapperFacade mapperFacade = CACHE_MAPPER_FACADE_MAP.get(mapKey);
if (Objects.isNull(mapperFacade)) {
MapperFactory factory = new DefaultMapperFactory.Builder().build();
ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass);
configMap.forEach(classMapBuilder::field);
classMapBuilder.byDefault().register();
mapperFacade = factory.getMapperFacade();
CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade);
}
return mapperFacade;
}

}

Good Good study,Day Day up!

git上找到的数据笔记大全

Read more »