威海建设集团信息网站,wordpress自动提交,个人网页制作代码模板,抖音代运营带货费用怎么收费YOLOv7单目测距#xff08;python#xff09; 1. 相关配置2. 测距原理3. 相机标定3.1#xff1a;标定方法13.2#xff1a;标定方法2 4. 相机测距4.1 测距添加4.2 主代码 5. 实验效果 相关链接 1. YOLOV5 单目测距#xff08;python#xff09; 2. YOLOV5 单目跟踪… YOLOv7单目测距python 1. 相关配置2. 测距原理3. 相机标定3.1标定方法13.2标定方法2 4. 相机测距4.1 测距添加4.2 主代码 5. 实验效果 相关链接 1. YOLOV5 单目测距python 2. YOLOV5 单目跟踪python 3. YOLOV7 单目跟踪python 4. YOLOV5 双目测距python 5. YOLOV7 双目测距python 6. 具体实现效果已在Bilibili发布点击跳转
本篇博文工程源码下载 链接1https://download.csdn.net/download/qq_45077760/87708470 链接2https://github.com/up-up-up-up/yolov7_Monocular_ranging
文章结构前三章节和 YOLOV5 单目测距 这篇博文一样如看过该博文直接跳转第四章节
1. 相关配置
系统win 10 YOLO版本yolov7 拍摄视频设备安卓手机 电脑显卡NVIDIA 2080TiCPU也可以跑GPU只是起到加速推理效果
2. 测距原理
单目测距原理相较于双目十分简单无需进行立体匹配仅需利用下边公式线性转换即可 D (F*W)/P其中D是目标到摄像机的距离, 是摄像机焦距焦距需要自己进行标定获取, W是目标的宽度或者高度行人检测一般以人的身高为基准, P是指目标在图像中所占据的像素 了解基本原理后下边就进行实操阶段
3. 相机标定
3.1标定方法1
可以参考张学友标定法获取相机的焦距
3.2标定方法2
直接使用代码获得焦距需要提前拍摄一个矩形物体拍摄时候相机固定距离被拍摄物体自行设定并一直保持此距离背景为纯色不要出现杂物最后将拍摄的视频用以下代码检测
import cv2win_width 1920
win_height 1080
mid_width int(win_width / 2)
mid_height int(win_height / 2)foc 1990.0 # 根据教程调试相机焦距
real_wid 9.05 # A4纸横着的时候的宽度视频拍摄A4纸要横拍镜头横A4纸也横
font cv2.FONT_HERSHEY_SIMPLEX
w_ok 1capture cv2.VideoCapture(5.mp4)
capture.set(3, win_width)
capture.set(4, win_height)while (True):ret, frame capture.read()# frame cv2.flip(frame, 1)if ret False:breakgray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray cv2.GaussianBlur(gray, (5, 5), 0)ret, binary cv2.threshold(gray, 140, 200, 60) # 扫描不到纸张轮廓时要更改阈值直到方框紧密框住纸张kernel cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))binary cv2.dilate(binary, kernel, iterations2)contours, hierarchy cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# cv2.drawContours(frame, contours, -1, (0, 255, 0), 2) # 查看所检测到的轮框for c in contours:if cv2.contourArea(c) 1000: # 对于矩形区域只显示大于给定阈值的轮廓所以一些微小的变化不会显示。对于光照不变和噪声低的摄像头可不设定轮廓最小尺寸的阈值continuex, y, w, h cv2.boundingRect(c) # 该函数计算矩形的边界框if x mid_width or y mid_height:continueif (x w) mid_width or (y h) mid_height:continueif h w:continueif x 0 or y 0:continueif x win_width or y win_height:continuew_ok wcv2.rectangle(frame, (x 1, y 1), (x w_ok - 1, y h - 1), (0, 255, 0), 2)dis_inch (real_wid * foc) / (w_ok - 2)dis_cm dis_inch * 2.54# os.system(cls)# print(Distance : , dis_cm, cm)frame cv2.putText(frame, %.2fcm % (dis_cm), (5, 25), font, 0.8, (0, 255, 0), 2)frame cv2.putText(frame, , (mid_width, mid_height), font, 1.0, (0, 255, 0), 2)cv2.namedWindow(res, 0)cv2.namedWindow(gray, 0)cv2.resizeWindow(res, win_width, win_height)cv2.resizeWindow(gray, win_width, win_height)cv2.imshow(res, frame)cv2.imshow(gray, binary)c cv2.waitKey(40)if c 27: # 按退出键esc关闭窗口breakcv2.destroyAllWindows()反复调节 ret, binary cv2.threshold(gray, 140, 200, 60)这一行里边的三个参数直到线条紧紧包裹住你所拍摄视频的物体然后调整相机焦距直到左上角距离和你拍摄视频时相机到物体的距离接近为止 然后将相机焦距写进测距代码distance.py文件里这里行人用高度表示根据公式 D (F*W)/P知道相机焦距F、行人的高度66.9单位英寸→170cm/2.54、像素点距离 h即可求出相机到物体距离D。 这里用到h-2是因为框的上下边界像素点不接触物体
foc 1990.0 # 镜头焦距
real_hight_person 66.9 # 行人高度
real_hight_car 57.08 # 轿车高度# 自定义函数单目测距
def person_distance(h):dis_inch (real_hight_person * foc) / (h - 2)dis_cm dis_inch * 2.54dis_cm int(dis_cm)dis_m dis_cm/100return dis_mdef car_distance(h):dis_inch (real_hight_car * foc) / (h - 2)dis_cm dis_inch * 2.54dis_cm int(dis_cm)dis_m dis_cm/100return dis_m4. 相机测距
4.1 测距添加
主要是把测距部分加在了画框附近首先提取边框的像素点坐标然后计算边框像素点高度在根据 公式 D (F*W)/P 计算目标距离
for *xyxy, conf, cls in reversed(det):if save_txt: # Write to filexywh (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywhline (cls, *xywh, conf) if opt.save_conf else (cls, *xywh) # label formatwith open(txt_path .txt, a) as f:f.write((%g * len(line)).rstrip() % line \n)if save_img or view_img: # Add bbox to imagex1 int(xyxy[0]) # 获取四个边框坐标y1 int(xyxy[1])x2 int(xyxy[2])y2 int(xyxy[3])h y2 - y1label f{names[int(cls)]} {conf:.2f}if label is not None:if (label.split())[0] person:dis_m person_distance(h) # 调用函数计算行人实际距离label f {dis_m}m # 将行人距离显示写在标签后plot_one_box(xyxy, im0, labellabel, colorcolors[int(cls)], line_thickness1)if (label.split())[0] car or (label.split())[0] truck:dis_m car_distance(h) # 调用函数计算行人实际高度label f {dis_m}m # 将行人距离显示写在标签后plot_one_box(xyxy, im0, labellabel, colorcolors[int(cls)], line_thickness1)4.2 主代码
import argparse
import time
from pathlib import Pathimport cv2
import torch
import torch.backends.cudnn as cudnn
from numpy import randomfrom models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages
from utils.general import check_img_size, check_requirements, check_imshow, non_max_suppression, apply_classifier, \scale_coords, xyxy2xywh, strip_optimizer, set_logging, increment_path
from utils.plots import plot_one_box
from utils.torch_utils import select_device, load_classifier, time_synchronized, TracedModel
from distance import person_distance,car_distancedef detect(save_imgFalse):source, weights, view_img, save_txt, imgsz, trace opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size, not opt.no_tracesave_img not opt.nosave and not source.endswith(.txt) # save inference imageswebcam source.isnumeric() or source.endswith(.txt) or source.lower().startswith((rtsp://, rtmp://, http://, https://))# Directoriessave_dir Path(increment_path(Path(opt.project) / opt.name, exist_okopt.exist_ok)) # increment run(save_dir / labels if save_txt else save_dir).mkdir(parentsTrue, exist_okTrue) # make dir# Initializeset_logging()device select_device(opt.device)half device.type ! cpu # half precision only supported on CUDA# Load modelmodel attempt_load(weights, map_locationdevice) # load FP32 modelstride int(model.stride.max()) # model strideimgsz check_img_size(imgsz, sstride) # check img_sizeif trace:model TracedModel(model, device, opt.img_size)if half:model.half() # to FP16# Second-stage classifierclassify Falseif classify:modelc load_classifier(nameresnet101, n2) # initializemodelc.load_state_dict(torch.load(weights/resnet101.pt, map_locationdevice)[model]).to(device).eval()# Set Dataloadervid_path, vid_writer None, Noneif webcam:view_img check_imshow()cudnn.benchmark True # set True to speed up constant image size inferencedataset LoadStreams(source, img_sizeimgsz, stridestride)else:dataset LoadImages(source, img_sizeimgsz, stridestride)# Get names and colorsnames model.module.names if hasattr(model, module) else model.namescolors [[random.randint(0, 255) for _ in range(3)] for _ in names]# Run inferenceif device.type ! cpu:model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) # run onceold_img_w old_img_h imgszold_img_b 1t0 time.time()for path, img, im0s, vid_cap in dataset:img torch.from_numpy(img).to(device)img img.half() if half else img.float() # uint8 to fp16/32img / 255.0 # 0 - 255 to 0.0 - 1.0if img.ndimension() 3:img img.unsqueeze(0)# Warmupif device.type ! cpu and (old_img_b ! img.shape[0] or old_img_h ! img.shape[2] or old_img_w ! img.shape[3]):old_img_b img.shape[0]old_img_h img.shape[2]old_img_w img.shape[3]for i in range(3):model(img, augmentopt.augment)[0]# Inferencet1 time_synchronized()with torch.no_grad(): # Calculating gradients would cause a GPU memory leakpred model(img, augmentopt.augment)[0]t2 time_synchronized()# Apply NMSpred non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classesopt.classes, agnosticopt.agnostic_nms)t3 time_synchronized()# Apply Classifierif classify:pred apply_classifier(pred, modelc, img, im0s)# Process detectionsfor i, det in enumerate(pred): # detections per imageif webcam: # batch_size 1p, s, im0, frame path[i], %g: % i, im0s[i].copy(), dataset.countelse:p, s, im0, frame path, , im0s, getattr(dataset, frame, 0)p Path(p) # to Pathsave_path str(save_dir / p.name) # img.jpgtxt_path str(save_dir / labels / p.stem) ( if dataset.mode image else f_{frame}) # img.txtgn torch.tensor(im0.shape)[[1, 0, 1, 0]] # normalization gain whwhif len(det):# Rescale boxes from img_size to im0 sizedet[:, :4] scale_coords(img.shape[2:], det[:, :4], im0.shape).round()# Print resultsfor c in det[:, -1].unique():n (det[:, -1] c).sum() # detections per classs f{n} {names[int(c)]}{s * (n 1)}, # add to string# Write resultsfor *xyxy, conf, cls in reversed(det):if save_txt: # Write to filexywh (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywhline (cls, *xywh, conf) if opt.save_conf else (cls, *xywh) # label formatwith open(txt_path .txt, a) as f:f.write((%g * len(line)).rstrip() % line \n)if save_img or view_img: # Add bbox to imagex1 int(xyxy[0]) # 获取四个边框坐标y1 int(xyxy[1])x2 int(xyxy[2])y2 int(xyxy[3])h y2 - y1label f{names[int(cls)]} {conf:.2f}if label is not None:if (label.split())[0] person:dis_m person_distance(h) # 调用函数计算行人实际高度label f {dis_m}m # 将行人距离显示写在标签后plot_one_box(xyxy, im0, labellabel, colorcolors[int(cls)], line_thickness1)if (label.split())[0] car or (label.split())[0] truck:dis_m car_distance(h) # 调用函数计算行人实际高度label f {dis_m}m # 将行人距离显示写在标签后plot_one_box(xyxy, im0, labellabel, colorcolors[int(cls)], line_thickness1)# Print time (inference NMS)print(f{s}Done. ({(1E3 * (t2 - t1)):.1f}ms) Inference, ({(1E3 * (t3 - t2)):.1f}ms) NMS)# Stream resultsif view_img:cv2.imshow(str(p), im0)cv2.waitKey(1) # 1 millisecond# Save results (image with detections)if save_img:if dataset.mode image:cv2.imwrite(save_path, im0)print(f The image with the result is saved in: {save_path})else: # video or streamif vid_path ! save_path: # new videovid_path save_pathif isinstance(vid_writer, cv2.VideoWriter):vid_writer.release() # release previous video writerif vid_cap: # videofps vid_cap.get(cv2.CAP_PROP_FPS)w int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))h int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))else: # streamfps, w, h 30, im0.shape[1], im0.shape[0]save_path .mp4vid_writer cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*mp4v), fps, (w, h))vid_writer.write(im0)if save_txt or save_img:s f\n{len(list(save_dir.glob(labels/*.txt)))} labels saved to {save_dir / labels} if save_txt else #print(fResults saved to {save_dir}{s})print(fDone. ({time.time() - t0:.3f}s))if __name__ __main__:parser argparse.ArgumentParser()parser.add_argument(--weights, nargs, typestr, defaultyolov7.pt, helpmodel.pt path(s))parser.add_argument(--source, typestr, defaultinference/images/2.mp4, helpsource) # file/folder, 0 for webcamparser.add_argument(--img-size, typeint, default640, helpinference size (pixels))parser.add_argument(--conf-thres, typefloat, default0.25, helpobject confidence threshold)parser.add_argument(--iou-thres, typefloat, default0.45, helpIOU threshold for NMS)parser.add_argument(--device, default, helpcuda device, i.e. 0 or 0,1,2,3 or cpu)parser.add_argument(--view-img, actionstore_true, helpdisplay results)parser.add_argument(--save-txt, actionstore_true, helpsave results to *.txt)parser.add_argument(--save-conf, actionstore_true, helpsave confidences in --save-txt labels)parser.add_argument(--nosave, actionstore_true, helpdo not save images/videos)parser.add_argument(--classes, nargs, typeint, helpfilter by class: --class 0, or --class 0 2 3)parser.add_argument(--agnostic-nms, actionstore_true, helpclass-agnostic NMS)parser.add_argument(--augment, actionstore_true, helpaugmented inference)parser.add_argument(--update, actionstore_true, helpupdate all models)parser.add_argument(--project, defaultruns/detect, helpsave results to project/name)parser.add_argument(--name, defaultexp, helpsave results to project/name)parser.add_argument(--exist-ok, actionstore_true, helpexisting project/name ok, do not increment)parser.add_argument(--no-trace, actionstore_true, helpdont trace model)opt parser.parse_args()print(opt)#check_requirements(exclude(pycocotools, thop))with torch.no_grad():if opt.update: # update all models (to fix SourceChangeWarning)for opt.weights in [yolov7.pt]:detect()strip_optimizer(opt.weights)else:detect()5. 实验效果
由于yolov7和yolov5机制问题yolov7推理时间相较于yolov5较长实验效果如下 更多有关测距的代码见我博客主页