1.准备数据集,做好相应尺寸
代码中示例为320,从原始大图变成320*320,加上letterbox和坐标变换
import os
import shutil
from tqdm import tqdm
import cv2
def my_letter_box(img,size=(320,320)): #
h,w,c = img.shape
r = min(size[0]/h,size[1]/w)
new_h,new_w = int(h*r),int(w*r)
top = int((size[0]-new_h)/2)
left = int((size[1]-new_w)/2)
bottom = size[0]-new_h-top
right = size[1]-new_w-left
img_resize = cv2.resize(img,(new_w,new_h))
img = cv2.copyMakeBorder(img_resize,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT,value=(114,114,114))
return img,r,left,top
SRC_DIR = r"/data/detect/2/"
DST_DIR_IMG = r"/data/Hdetect/images320/"
DST_DIR_LABELS = r"/data/detect/labels320/"
imglist = os.listdir(SRC_DIR)
for file in tqdm(imglist):
if not file.endswith(".jpg"):
continue
name = file.split(".jpg")[0]
if not os.path.exists(SRC_DIR+name+".txt"):
continue
#shutil.copy(SRC_DIR+file,DST_DIR_IMG+file)
img =cv2.imread(SRC_DIR+file)
h_img,w_img,c= img.shape
img_letter,rr,left,top= my_letter_box(img)
cv2.imwrite(DST_DIR_IMG+file,img_letter)
with open(os.path.join(SRC_DIR, name+".txt"), 'r', encoding="utf-8") as r:
label_list = r.readlines()
with open(os.path.join(DST_DIR_LABELS, name+".txt"), 'a+') as ftxt:
for label in label_list:
label1 = [x for x in label.split(" ") if x != ""]
class_name =label1[0]
x = float(label1[1])
y = float(label1[2])
w = float(label1[3])
h = float(label1[4])
ww = w_img*w
hh = h_img*h
xx1 = (x-w/2)*w_img
yy1 = (y-h/2)*h_img
xx2 = ww+xx1
yy2 = hh+yy1
x_letter_1 = (xx1)*rr+left
y_letter_1 = (yy1)*rr+top
x_letter_2 = (xx2)*rr+left
y_letter_2 = (yy2)*rr+top
#print("x=",x)
#print("h=",h)
#ftxt.writelines(class_name + " " + str(xx1) + " " + str(yy1)+" " + str(xx2) + " "+str(yy2) + '\n')
ftxt.writelines(class_name + " " + str(x_letter_1) + " " + str(y_letter_1)+" " + str(x_letter_2) + " "+str(y_letter_2) + '\n')
ftxt.close()
2.端侧检测结果形式
3.将图像转换为端侧推理形式(可选)
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Copyright (C) Shenshu Technologies Co., Ltd. 2022-2022. All rights reserved.
import numpy as np
import os
from PIL import Image
def process(input_path,out_dir):
try:
input_image = Image.open(input_path)
input_image = input_image.resize((320, 320), resample=Image.BILINEAR)
# hwc
img = np.array(input_image)
height = img.shape[0]
width = img.shape[1]
h_off = int((height-320)/2)
w_off = int((width-320)/2)
crop_img = img[h_off:height-h_off, w_off:width-w_off, :]
# rgb to bgr
img = crop_img[:, :, ::-1]
#img = crop_img[:, :, :]
shape = img.shape
img = img.astype("int8")
img = img.reshape([1] + list(shape))
result = img.transpose([0, 3, 1, 2])
output_name = out_dir +input_path.split("/")[-1].rsplit('.', 1)[0] + ".bin"
result.tofile(output_name)
except Exception as except_err:
print(except_err)
return 1
else:
return 0
if __name__ == "__main__":
count_ok = 0
count_ng = 0
images = os.listdir(r'./images320')
dir = os.path.realpath("./images320")
out_dir = "./images320_bin/"
for image_name in images:
if not (image_name.lower().endswith((".bmp", ".dib", ".jpeg", ".jpg", ".jpe",
".png", ".pbm", ".pgm", ".ppm", ".sr", ".ras", ".tiff", ".tif"))):
continue
print("start to process image {}....".format(image_name))
image_path = os.path.join(dir, image_name)
ret = process(image_path,out_dir)
if ret == 0:
print("process image {} successfully".format(image_name))
count_ok = count_ok + 1
elif ret == 1:
print("failed to process image {}".format(image_name))
count_ng = count_ng + 1
print("{} images in total, {} images process successfully, {} images process failed"
.format(count_ok + count_ng, count_ok, count_ng))
4.将端侧的格式转换乘map工程所使用的格式
#####批量处理
from cProfile import label
import shutil
from tkinter.messagebox import NO
import cv2
import os
images_path = "/data//images320"
txt_name = "/data/detect/result_detect.txt"
save_path_labels = "/data/detect/resultdetect_3403"
img_path_last = ""
labels_num = 0
a=0
imgs_count = 0
for line in open(txt_name):
print(line)
line_len=len(line.split(" "))
img_name = line.split(" ")[0].split("/")[-1].replace('.bin','.jpg')
#img_name = line.split(" ")[0].split("/")[-1]
img_path = os.path.join(images_path, img_name)
if line_len==1:
save_txt = os.path.join(save_path_labels, img_name.replace('.jpg\n', '.txt'))
txt_file = open(save_txt, 'a')
labels_num = labels_num+1
else:
img_name = line.split(" ")[0].split("/")[-1].replace('.bin','.jpg')
#img_name = line.split(" ")[0].split("/")[-1]
img_path = os.path.join(images_path, img_name)
shape =(320,320)
new_shape = (320, 320)
r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
r = min(r, 1.0)
ratio = r, r # width, height ratios
new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
dw /= 2 # divide padding into 2 sides
dh /= 2
label = line.split(" ")[1]
x_min = int(float(line.split(" ")[4]))
x_max = int(float(line.split(" ")[6]))
y_min = int(float(line.split(" ")[5]))
y_max = int(float(line.split(" ")[7].strip('\n')))
#x_min = int(480*float(line.split(" ")[4])/640)
#x_max = int(480*float(line.split(" ")[6])/640)
#y_min = int(480*float(line.split(" ")[5])/640)
#y_max = int(480*float(line.split(" ")[7].strip('\n'))/640)
conf = float(line.split(" ")[3])
# 计算xywh
x_min_new = max(int((x_min-dw) / new_unpad[0] * shape[1]),0)
x_max_new = min(int((x_max-dw) / new_unpad[0] * shape[1]),shape[1])
y_min_new = max(int((y_min-dh) / new_unpad[1] * shape[0]),0)
y_max_new = min(int((y_max-dh) / new_unpad[1] * shape[0]),shape[0])
save_txt = os.path.join(save_path_labels, img_name.replace('.jpg', '.txt'))
txt_file = open(save_txt, 'a')
txt_file.write(str(label) + ' ' + str(conf)+' '+str(x_min_new) + ' ' + str(y_min_new) + ' ' + str(x_max_new) + ' ' + str(
y_max_new) + '\n')
print(labels_num)
print(a)
print(imgs_count)
5.比较增加没有检测结果的txt文本
import os
import shutil
from tqdm import tqdm
DIR_PATH_GT= r"/data/detect/labels320/"
data_list_gt = os.listdir(DIR_PATH_GT)
DIR_PATH_haisi = r"/data/detect/result_detect/"
data_list_haisi = os.listdir(DIR_PATH_haisi)
for plate_path in tqdm(data_list_gt):
if not plate_path in data_list_haisi:
save_txt = os.path.join(r"/data//result_plate", plate_path)
txt_file = open(save_txt, 'a')
6.map计算脚本
参考:https://github.com/Cartucho/mAP/tree/master
import glob
import json
import os
import shutil
import operator
import sys
import argparse
import math
import numpy as np
MINOVERLAP = 0.5
parser = argparse.ArgumentParser()
parser.add_argument('-na', '--no-animation', help="no animation is shown.", action="store_true")
parser.add_argument('-np', '--no-plot', help="no plot is shown.", action="store_true")
parser.add_argument('-q', '--quiet', help="minimalistic console output.", action="store_true")
parser.add_argument('-i', '--ignore', nargs='+', type=str, help="ignore a list of classes.")
parser.add_argument('--set-class-iou', nargs='+', type=str, help="set IoU for a specific class.")
args = pars