目标检测代码

血细胞检测

数据集

参考网址

faster R-CNN

weights -500epochs

使用faster R-CNN框架,csv自定义数据集。基于tensorflow和keras。

数据集处理

csv文件要求的格式为:filepath,x1,y1,x2,y2,class_name

BCCD数据集中已经给好了一个csv格式的test:

image-20201030171640408

train.txt test.txt给出了训练集和测试集的图片名:

image-20201030171927992

将给出的test.csv重命名为all.csv,按照train.txt和test.txt给出相应的train.csv和test.csv

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
import csv

file = open('./test.csv')
train = open('./train.txt')
test = open('./test.txt')

trainList = train.read().splitlines() # 205
testList = test.read().splitlines() # 72
lines = file.read().splitlines() # 4889

file.close()
train.close()
test.close()

all = []
for line in lines:
line = line.split(',')
line[0] = line[0].replace('.jpg', '')
all.append(line)

all = all[1:] #第一行为filename等文件头

traincsv = [["image_names", "cell_type", "xmin", "xmax", "ymin", "ymax"]] # 2805
testcsv = [["image_names", "cell_type", "xmin", "xmax", "ymin", "ymax"]] # 2083

for i in all:
if i[0] in trainList:
traincsv.append(i)
else:
testcsv.append(i)


def write(name, row):
with open(name + '.csv', 'w', newline='')as csvfile:
writer = csv.writer(csvfile)
for c in row:
writer.writerow(c)


write("train", traincsv)
write("test", testcsv)

训练时需要的是txt文件,将csv转为txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pandas as pd

train = pd.read_csv('train.csv')

data = pd.DataFrame()
data['format'] = train['image_names']

# as the images are in train_images folder, add train_images before the image name
for i in range(data.shape[0]):
data['format'][i] = 'path' + data['format'][i]+'.jpg'

# add xmin, ymin, xmax, ymax and class as per the format required
for i in range(data.shape[0]):
data['format'][i] = data['format'][i] + ',' + str(train['xmin'][i]) + ',' + str(train['ymin'][i]) + ',' + str(train['xmax'][i]) + ',' + str(train['ymax'][i]) + ',' + train['cell_type'][i]

data.to_csv('annotate.txt', header=None, index=None, sep=' ')

train

1
2
cd keras-frcnn
python train_frcnn.py -o simple -p annotate.txt

test

测试时需要把测试用的图片放到一个文件夹下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
import shutil
import os

test = pd.read_csv('test.csv')
names = test['image_names'].unique()

oldpath = '...\BCCD\JPEGImages\\'
newpath = '...\keras-frcnn\\test_images\\'

for name in names:
if os.path.exists(oldpath+name+'.jpg'):
shutil.copy(oldpath+name+'.jpg', newpath+name+'.jpg')
else:
continue

test_frcnn.py最后改成

1
2
3
# cv2.imshow('img',img)
# cv2.waitKey(0)
cv2.imwrite('./results_imgs/{}.png'.format(os.path.splitext(str(img_name))[0]), img)

结果

image-20201030173531155

RetinaNet on coco

源码

coco数据集在aistudio里下载

1
2
3
4
5
用coco数据集的话,整理成以下形式

val2017 ---- annotations ---- instances_val2017.json
|
-- images ---- val2017

coco

训练

1
python train.py --dataset coco --coco_path E:\Python\ObjDetection\datasets\val2017 --depth 50

测试

1
python coco_validation.py --coco_path E:\Python\ObjDetection\datasets\val2017 --model_path ./coco_resnet_50_map_0_335_state_dict.pt

指定图片可视化

将需要可视化的图片放到visual文件夹里

需要修改一部分代码,源码只加载了state_dict没有指定模型,在visulize_single_image.py中导入retinanet

from retinanet import model,然后代码里先指定模型

1
2
3
4
5
6
retina = model.resnet50(num_classes=80)
retina.load_state_dict(torch.load(model_path))
if torch.cuda.is_available():
retina = retina.cuda()
retina.training = False
retina.eval()
1
python visualize_single_image.py --image_dir ./visual --model_path ./coco_resnet_50_map_0_335_state_dict.pt --class_list ./coco_classes_list.csv

这种方法还需要生成coco的classes_list格式为 class_name,id

image-20201030174851530

coco可视化

同样需要加载retinanet模型

1
2
retinanet = model.resnet50(num_classes=80)
retinanet.load_state_dict(torch.load(parser.model))
1
python visualize.py --dataset coco --coco_path ...\datasets\val2017 --model ./coco_resnet_50_map_0_335_state_dict.pt

image-20201030175010707

按下键换下一张图片

csv

按照要求生成如下格式的csv文件,‘path/to/image.jpg,x1,y1,x2,y2,class_name’

用百度的fruit数据集,解析xml文件,生成train.csv、test.csv、classes.csv

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
<annotation>
<folder>train</folder>
<filename>apple_3.jpg</filename>
<path>C:\tensorflow1\models\research\object_detection\images\train\apple_3.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>1000</width>
<height>708</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>apple</name>
<pose>Unspecified</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>584</xmin>
<ymin>438</ymin>
<xmax>867</xmax>
<ymax>708</ymax>
</bndbox>
</object>
<object>
<name>apple</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>492</xmin>
<ymin>141</ymin>
<xmax>740</xmax>
<ymax>394</ymax>
</bndbox>
</object>
<object>
<name>apple</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>176</xmin>
<ymin>199</ymin>
<xmax>490</xmax>
<ymax>466</ymax>
</bndbox>
</object>
<object>
<name>apple</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>367</xmin>
<ymin>17</ymin>
<xmax>619</xmax>
<ymax>240</ymax>
</bndbox>
</object>
<object>
<name>apple</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>642</xmin>
<ymin>35</ymin>
<xmax>907</xmax>
<ymax>269</ymax>
</bndbox>
</object>
</annotation>
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
import csv
import xml.etree.ElementTree as ET
import os


def createall():
filepath = "...\datasets\\fruit-detection\Annotations"
pathdir = os.listdir(filepath)
List = []
for file in pathdir:
temppath = filepath + '\\' + file
tree = ET.parse(temppath)
root = tree.getroot()
for i in root.iter('object'):
temp = []
temp.append("...\datasets\\fruit-detection\JPEGImages\\"+file.split('.')[0]+'.jpg')
for j in i.find('bndbox'):
temp.append(j.text)
temp.append(root.find('object').find('name').text)
List.append(temp)
write("all", List)


def write(name, row):
with open(name + '.csv', 'w', newline='')as csvfile:
writer = csv.writer(csvfile)
for c in row:
writer.writerow(c)


def createsplit():
trainfile = open("...\datasets\\fruit-detection\ImageSets\Main\\train.txt")
allcsv = open("./all.csv")
List = allcsv.read().splitlines()
lines = trainfile.readlines()
lines = [i.strip() for i in lines]
trainfile.close()
allcsv.close()
trainlist = []
vallist = []
for i in List:
if i.strip().split('.')[0].split('\\')[-1] in lines:
trainlist.append(i.split(','))
else:
vallist.append(i.split(','))
write("train", trainlist)
write("val", vallist)


def createclass():
L = [['apple', 0], ['banana', 1], ['orange', 2]]
write('classes', L)


# write("all", List)
# createaplit()
createsplit()

训练

  • Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm)

    出现这个错误的情况是,在服务器上的docker中运行训练代码时,batch size设置得过大,shared memory不够(因为docker限制了shm).解决方法是,将Dataloader的num_workers设置为0.

1
CUDA_VISIBLE_DEVICES=4 python ./train.py --dataset csv --csv_train ./csv/train1.csv --csv_classes ./csv/classes.csv --csv_val ./csv/val1.csv
  • Attempted to read a PyTorch file with version 3, but the maximum supported version for reading is 2.

因为服务器版本和本机版本不一致,但更新了conda还是不行

修改visualize_single_image

1
2
3
4
# cv2.imshow('detections', image_orig)
# cv2.waitKey(0)
print(img_name)
cv2.imwrite('./fruit_results/{}.png'.format(img_name.split('.')[0]), image_orig)

直接将图片保存在服务器上

1
CUDA_VISIBLE_DEVICES=4 python ./visualize_single_image.py --image_dir ./visual_fruit --model_path ./checkpoint/model_final.pt --class_list ./fruit_classes_list.csv

img

img