news 2026/10/22 12:22:15

【深度学习】DBFace: 源码阅读(三)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【深度学习】DBFace: 源码阅读(三)

7 推断部分

推断部分主要是在test.py中

主要函数其实很短,如下,代码其实被我改了一部分,和原始的github上可能有点区别

mean=[0.408,0.447,0.47]std=[0.289,0.274,0.278]# trial_name = "small-H-dense-wide64-UCBA-keep12-noext-ignoresmall2"trial_name="mv2-320x320-without-wf_20200811"jobdir=f"jobs/{trial_name}"image=common.imread("imgs/selfie.jpg")model=DBFace(has_landmark=True,wide=64,has_ext=True,upmode="DeCBA")model.load(f"{jobdir}/models/74.pth")model.eval()model.cuda()outs=eval_tool.detect_image(model,image,mean,std,0.2)outs=nms(outs,0.2)print("objs = %d"%len(outs))forobjinouts:common.drawbbox(image,obj)common.imwrite(f"{jobdir}/result.jpg",image)print("ok")

model.load()下载对应的模型,推断最主要的函数是

outs=eval_tool.detect_image(model,image,mean,std,0.2)

我们来看下detect_image函数:

defdetect_image(model,image,mean,std,threshold=0.4):# pad主要是因为网络推断中stride=32,所以为了保证可以上采样回去,需要进行pad操作image=common.pad(image)#预处理操作image=((image/255-mean)/std).astype(np.float32)image=image.transpose(2,0,1)image=torch.from_numpy(image).unsqueeze(0).cuda()# 推断center,box,landmark=model(image)#得到结果回归框中心点的heatmap,通过sigmoid来得到0-1center=center.sigmoid()box=torch.exp(box)# debug# center = F.max_pool2d(center, kernel_size=3, padding=1, stride=1)returndetect_images_giou_with_netout(center,box,landmark,threshold)

我们再来看下detect_images_giou_with_netout这个函数:

defdetect_images_giou_with_netout(output_hm,output_tlrb,output_landmark,threshold=0.4,ibatch=0):stride=4_,num_classes,hm_height,hm_width=output_hm.shape hm=output_hm[ibatch].reshape(1,num_classes,hm_height,hm_width)tlrb=output_tlrb[ibatch].cpu().data.numpy().reshape(1,num_classes*4,hm_height,hm_width)# landmark = output_landmark[ibatch].cpu().data.numpy().reshape(1, num_classes * 10, hm_height, hm_width)landmark=output_landmark[ibatch].cpu().data.numpy().reshape(1,num_classes*50,hm_height,hm_width)# 使用最大池化来筛选值nmskey=_nms(hm,3)# 选出top值2000,人脸较多的情况下值可以大一些,但是如果人脸比较少,或者图像比较小,建议还是小一些kscore,kinds,kcls,kys,kxs=_topk(nmskey,2000)kys=kys.cpu().data.numpy().astype(np.int)kxs=kxs.cpu().data.numpy().astype(np.int)kcls=kcls.cpu().data.numpy().astype(np.int)key=[[],[],[],[]]forindinrange(kscore.shape[1]):score=kscore[0,ind]ifscore>threshold:key[0].append(kys[0,ind])key[1].append(kxs[0,ind])key[2].append(score)key[3].append(kcls[0,ind])imboxs=[]ifkey[0]isnotNoneandlen(key[0])>0:ky,kx=key[0],key[1]classes=key[3]scores=key[2]foriinrange(len(kx)):class_=classes[i]cx,cy=kx[i],ky[i]x1,y1,x2,y2=tlrb[0,class_*4:(class_+1)*4,cy,cx]x1,y1,x2,y2=(np.array([cx,cy,cx,cy])+np.array([-x1,-y1,x2,y2]))*stride# 根据关键点个数进行修改# x5y5 = landmark[0, 0:10, cy, cx]# x5y5 = np.array(common.exp(x5y5 * 4))# x5y5 = (x5y5 + np.array([cx] * 5 + [cy] * 5)) * stride# boxlandmark = list(zip(x5y5[:5], x5y5[5:]))x5y5=landmark[0,0:50,cy,cx]#注意这个exp()x5y5=np.array(common.exp(x5y5*4))x5y5=(x5y5+np.array([cx]*25+[cy]*25))*stride boxlandmark=list(zip(x5y5[:25],x5y5[25:]))imboxs.append(common.BBox(label=str(class_),xyrb=common.floatv([x1,y1,x2,y2]),score=scores[i].item(),landmark=boxlandmark))returnimboxs

最后将返回得到的候选框和关键点坐标在通过nms进行处理

defnms(objs,iou=0.5):ifobjsisNoneorlen(objs)<=1:returnobjs objs=sorted(objs,key=lambdaobj:obj.score,reverse=True)keep=[]flags=[0]*len(objs)forindex,objinenumerate(objs):ifflags[index]!=0:continuekeep.append(obj)forjinrange(index+1,len(objs)):ifflags[j]==0andobj.iou(objs[j])>iou:flags[j]=1returnkeep

使用NMS来去除冗余的框,得到最后的结果

当中,其实有些细节,例如关键点的后处理要进行exp():

defexp(v):ifisinstance(v,tuple)orisinstance(v,list):return[exp(item)foriteminv]elifisinstance(v,np.ndarray):returnnp.array([exp(item)foriteminv],v.dtype)gate=1base=np.exp(1)ifabs(v)<gate:returnv*baseifv>0:returnnp.exp(v)else:return-np.exp(-v)

为什么呢?我们来看下作者是怎么解释的?

第三篇还是有些细节是需要注意的,后面一篇写下转caffemodel?还是其他呢。。。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 12:21:43

【caffe】Caffe:常用层的参数设置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:19:52

数字温度传感器双路测温:PIC32MZ与PJ85718DM长线I2C实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:19:19

PJ85718DM+STM32L151ZD温控信号链设计与低功耗协同实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:19:19

基于STM32与PJ85718DM的HVAC双通道测温方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:17:58

基于PJ85718DM与PIC18F87K22的双通道温度监测方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 12:16:58

PJ85718DM+STM32L151ZD温测方案:HVAC嵌入式温度监测硬件设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华