yolov3后处理,包括网络输出、阈值过滤、多类NMS

  • pytorch版本:1.7.1+cu101
from net.yolov3 import Yolo
from PIL import Image, ImageDraw
import numpy as np
import torch, copy, time

def sigmoid(x):
	temporary = 1 + torch.exp(-x)
	return 1.0 / temporary

def get_boxes(output, anchors):
	h = output.size(2)
	w = output.size(3)
	output = output.view(3, 85, h, w).permute(0,2,3,1)
	tc = torch.sigmoid(output[..., 4])    # 3*h*w
	cl = torch.sigmoid(output[..., 5:])   # 3*h*w*80
	clv, cli = torch.max(cl,-1)
	mask = tc * clv > 0.9
	# print(torch.where(mask))
	cli = cli[mask].unsqueeze(-1)
	# 3*h*w
	tx = torch.sigmoid(output[..., 0][mask])
	ty = torch.sigmoid(output[..., 1][mask])
	tw = torch.exp(output[..., 2][mask])
	th = torch.exp(output[..., 3][mask])
	# grid
	FloatTensor = torch.cuda.FloatTensor if tx.is_cuda else torch.FloatTensor
	grid_x, grid_y = torch.meshgrid(torch.linspace(0,w-1,w), torch.linspace(0,h-1,h))
	grid_x = grid_x.repeat(3,1,1)[mask].type(FloatTensor)
	grid_y = grid_y.repeat(3,1,1)[mask].type(FloatTensor)
	tx = ((tx+grid_y) / w).unsqueeze(-1)
	ty = ((ty+grid_x) / h).unsqueeze(-1)
	# anchor
	aw = torch.Tensor(anchors[0::2]).view(3,1).repeat(1,h*w).view(3,h,w)[mask].type(FloatTensor)
	ah = torch.Tensor(anchors[1::2]).view(3,1).repeat(1,h*w).view(3,h,w)[mask].type(FloatTensor)
	tw = (tw * aw).unsqueeze(-1)
	th = (th * ah).unsqueeze(-1)
	return torch.cat([tx, ty, tw, th, cli], -1)

def get_boxes(output, anchors):
	h=output.size(2)
	w=output.size(3)
	output=output.view(3,85,h,w).permute(0,2,3,1)
	# conf
	conf = torch.sigmoid(output[..., 4])
	cl = torch.sigmoid(output[..., 5:])
	clv, cli = torch.max(cl, -1)
	conf = conf * clv
	mask = conf > 0.5
	conf = conf[mask].unsqueeze(-1)
	cli = cli[mask].unsqueeze(-1)
	# grid
	FloatTensor = torch.cuda.FloatTensor if conf.is_cuda else torch.FloatTensor
	grid_h, grid_w = torch.meshgrid(torch.arange(h), torch.arange(w))
	grid_h = grid_h.repeat(3,1,1).type(FloatTensor)
	grid_w = grid_w.repeat(3,1,1).type(FloatTensor)
	tx = (torch.sigmoid(output[..., 0]) + grid_w) / w
	ty = (torch.sigmoid(output[..., 1]) + grid_h) / h
	tx = tx[mask].unsqueeze(-1)
	ty = ty[mask].unsqueeze(-1)
	# anchor
	aw = torch.Tensor(anchors[0::2]).view(3,1).repeat(1,h*w).view(3,h,w).type(FloatTensor)
	ah = torch.Tensor(anchors[1::2]).view(3,1).repeat(1,h*w).view(3,h,w).type(FloatTensor)
	tw = torch.exp(output[..., 2]) * aw
	th = torch.exp(output[..., 3]) * ah
	tw = tw[mask].unsqueeze(-1)
	th = th[mask].unsqueeze(-1)
	return torch.cat([tx, ty, tw, th, cli, conf], -1)

# def get_boxes(output, anchors):
# 	c = output.size(1)
# 	h = output.size(2)
# 	w = output.size(3)
# 	boxes = []
# 	output = output.view(3, 85, h, w).permute(0,2,3,1)
# 	for i in range(3):
# 		for j in range(h):
# 			for k in range(w):
# 				temporary = output[i][j][k]
# 				for t in range(5,85):
# 					if(sigmoid(temporary[4]) * sigmoid(temporary[t]) < 0.9): 
# 						continue
# 					x = (sigmoid(temporary[0]) + k) / w
# 					y = (sigmoid(temporary[1]) + j) / h
# 					tw = torch.exp(temporary[2]) * anchors[i*2]
# 					th = torch.exp(temporary[3]) * anchors[i*2+1]
# 					boxes.append([x,y,tw,th,t-5])
# 					print(i,j,k)
# 	return boxes

def iou(a,b):
	A=len(a)
	B=len(b)
	area1=a[:,2]*a[:,3]
	area1=area1.unsqueeze(1).expand(A,B)
	area2=b[:,2]*b[:,3]
	area2=area2.unsqueeze(0).expand(A,B)
	ba=torch.zeros(a.shape).cuda()
	bb=torch.zeros(b.shape).cuda()
	ba[:,0:2]=a[:,0:2]-a[:,2:]/2.0
	ba[:,2:]=ba[:,0:2]+a[:,2:]
	bb[:,0:2]=b[:,0:2]-b[:,2:]/2.0
	bb[:,2:]=bb[:,0:2]+b[:,2:]
	ba=ba.unsqueeze(1).expand(A,B,4)
	bb=bb.unsqueeze(0).expand(A,B,4)
	lt=torch.max(ba[:,:,0:2], bb[:,:,0:2])
	rb=torch.min(ba[:,:,2:], bb[:,:,2:])
	inter=torch.clamp((rb-lt),min=0)
	inter=inter[:,:,0]*inter[:,:,1]
	return inter/(area1+area2-inter)

def nms(box):
	box = box[torch.argsort(box[:,-1])]
	result=[]
	while len(box) > 0:
		result.append(box[0])
		if len(box) == 1: break
		ious=iou(box[0:1, 0:4], box[1:, 0:4])
		#print(ious)
		box=box[1:][ious.squeeze(0) < 0.5]
	return torch.stack(result)

def deal(boxes):
	labels = boxes[:, -2].unique()
	result=[]
	for l in labels:
		box = boxes[boxes[:, -2]==l]
		box = nms(box)
		for b in box: 
			result.append(b)
	return torch.stack(result)

classes=[]
for line in open('/home/lwd/code/darknet/data/coco.names'):
	classes.append(line[:-1])
model_path='/home/lwd/code/dl/myTorch/yolo/model/99.pth'
net=Yolo(80)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
paras=torch.load(model_path, map_location=device)

net.load_state_dict(paras)
net = net.eval()
net = net.cuda()

with open('result/log.txt', 'w') as f:
	for line in open('/home/lwd/data/20220220.txt'):
		f.write(line[:-1].split('/')[-1]+'\n')
		print(line[:-1])
		raw = Image.open(line[:-1])
		ih, iw = np.shape(raw)[0:2]
		image = raw.resize((416, 416), Image.BICUBIC)
		image = np.array(image, dtype='float32') / 255.0
		image = np.expand_dims(np.transpose(image, (2, 0, 1)), 0)
		with torch.no_grad():
			images = torch.from_numpy(image)
			images = images.cuda()
			outputs = net(images)
		anchors=[[116,90,  156,198,  373,326],[30,61,  62,45,  59,119],[10,13,  16,30,  33,23]]
		draw = ImageDraw.Draw(raw)
		thld_boxes=[]
		for i,output in enumerate(outputs):
			ti = time.time()
			boxes = get_boxes(output, anchors[i])
			if len(boxes) == 0: continue
			boxes[:,0] = boxes[:,0] * iw
			boxes[:,1] = boxes[:,1] * ih
			boxes[:,2] = boxes[:,2] / 416.0 * iw
			boxes[:,3] = boxes[:,3] / 416.0 * ih
			for b in boxes:
				thld_boxes.append(b)
			print(output.size(2), 'time: ', time.time()-ti)
		if len(thld_boxes) == 0: continue
		boxes=deal(torch.stack(thld_boxes))
		print(len(boxes))
		for b in boxes:
				cx = b[0]
				cy = b[1]
				w = b[2]
				h = b[3]
				draw.rectangle([cx-w/2, cy-h/2, cx+w/2, cy+h/2])
				draw.text((cx-w/2, cy-h/2), classes[int(b[4])], fill="#FF0000")
				f.write(classes[int(b[4])]+'\n')
			# if(len(boxes) > 0):break
		del draw
		# raw.show()
		raw.save('result/image/'+line[:-1].split('/')[-1])

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
YOLOv8后处理cpp是指在使用YOLOv8目标检测算法进行物体检测后,对检测结果进行进一步处理的过程。这个后处理cpp的主要目的是对检测结果进行筛选、分类和定位,以获得更准确的物体检测结果。 具体来说,后处理cpp通常包括以下几个步骤: 首先,对检测结果进行筛选,去除低置信度的边界框。一般会设置一个阈值,只保留置信度高于该阈值的边界框,以提高检测的准确性。 然后,对筛选后的边界框进行分类,判断每个边界框内的物体属于哪个类别。一般会使用预先训练好的分类模型来进行分类,根据物体的特征来确定其类别。这样可以将检测结果与已知类别进行匹配,得到更加具体的物体信息。 接下来,对分类后的边界框进行定位,确定物体在图像中的准确位置。这一步可以通过计算边界框的中心点坐标和宽高等参数来实现。通过定位,可以更精确地确定物体在图像中的位置。 最后,根据物体检测的结果,可以进行一系列的应用,比如目标跟踪、行为分析、智能监控等。这些应用可以根据具体情况进行选择和扩展,以满足不同的需求。 总之,YOLOv8后处理cpp通过筛选、分类和定位等步骤,对物体检测的结果进行进一步处理,提高检测的准确性和可用性。这个后处理cpp能够帮助我们更好地理解和利用物体检测的结果,为各种应用场景提供更精确的物体信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刀么克瑟拉莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值