yolov5.7 车辆检测资料自用+pycharm环境问题

数据集

1. kitti转yolo

参考:

标签整合与转xml
xml转txt+划分训练集

整合代码

! 文件最好与python放一个父文件夹内

KITTY2YOLO1.py 合并类
# modify_annotations_txt.py
# 合并类
import glob

import string

# kiiti 标签文件路径
txt_list = glob.glob('F:/database/database/KITTI-odom/data_object_label_2/training/label_2/*.txt')  # 存储Labels文件夹所有txt文件路径        注意要保留/*

print(txt_list)


def show_category(txt_list):
    category_list = []
    for item in txt_list:
        try:
            with open(item) as tdf:
                for each_line in tdf:
                    labeldata = each_line.strip().split(' ')  # 去掉前后多余的字符并把其分开
                    category_list.append(labeldata[0])  # 只要第一个字段,即类别
        except IOError as ioerr:
            print('File error:' + str(ioerr))
    print(set(category_list))  # 输出集合


def merge(line):
    each_line = ''
    for i in range(len(line)):
        if i != (len(line) - 1):
            each_line = each_line + line[i] + ' '
        else:
            each_line = each_line + line[i]  # 最后一条字段后面不加空格
    each_line = each_line + '\n'
    return (each_line)


print('before modify categories are:\n')

show_category(txt_list)
# 合并类
# 行人类:['Person_sitting','Cyclist','Pedestrian']
# 车辆类:['Truck','Van','Tram']
# 其他类:[ 'DontCare','Misc']
for item in txt_list:
    new_txt = []
    try:
        with open(item, 'r') as r_tdf:
            for each_line in r_tdf:
                labeldata = each_line.strip().split(' ')
                # if labeldata[0] in ['Truck','Van','Tram']: # 合并汽车类
                #     labeldata[0] = labeldata[0].replace(labeldata[0],'Car')
                if labeldata[0] == 'Person_sitting':  # 合并行人类
                # labeldata[0] = labeldata[0].replace(labeldata[0], 'Pedestrian')
                    continue # 忽略行人类
                if labeldata[0] == 'DontCare':  # 忽略Dontcare类
                    continue
                if labeldata[0] == 'Misc':  # 忽略Misc类
                    continue
                if labeldata[0] in ['Cyclist','Pedestrian']:  # 忽略整合后的行人类
                    continue
                new_txt.append(merge(labeldata))  # 重新写入新的txt文件
        with open(item, 'w+') as w_tdf:  # w+是打开原文件将内容删除,另写新内容进去
            for temp in new_txt:
                w_tdf.write(temp)
    except IOError as ioerr:
        print('File error:' + str(ioerr))

print('\nafter modify categories are:\n')
show_category(txt_list)


KITTI2YOLO.py 转为xml

记得好像是把kitti数据集丢进project文件夹才能用

# kitti_txt_to_xml.py
# encoding:utf-8
# 根据一个给定的XML Schema,使用DOM树的形式从空白文件生成一个XML
from xml.dom.minidom import Document
import cv2
import os
def generate_xml(name,split_lines,img_size,class_ind):
    doc = Document() # 创建DOM文档对象
    annotation = doc.createElement('annotation')
    doc.appendChild(annotation)
    title = doc.createElement('folder')
    title_text = doc.createTextNode('KITTI')
    title.appendChild(title_text)
    annotation.appendChild(title)
    img_name=name+'.png'
    title = doc.createElement('filename')
    title_text = doc.createTextNode(img_name)
    title.appendChild(title_text)
    annotation.appendChild(title)
    source = doc.createElement('source')
    annotation.appendChild(source)
    title = doc.createElement('database')
    title_text = doc.createTextNode('The KITTI Database')
    title.appendChild(title_text)
    source.appendChild(title)
    title = doc.createElement('annotation')
    title_text = doc.createTextNode('KITTI')
    title.appendChild(title_text)
    source.appendChild(title)
    size = doc.createElement('size')
    annotation.appendChild(size)
    title = doc.createElement('width')
    title_text = doc.createTextNode(str(img_size[1]))
    title.appendChild(title_text)
    size.appendChild(title)
    title = doc.createElement('height')
    title_text = doc.createTextNode(str(img_size[0]))
    title.appendChild(title_text)
    size.appendChild(title)
    title = doc.createElement('depth')
    title_text = doc.createTextNode(str(img_size[2]))
    title.appendChild(title_text)
    size.appendChild(title)
    for split_line in split_lines:
        line=split_line.strip().split()
        if line[0] in class_ind:
            object = doc.createElement('object')
            annotation.appendChild(object)
            title = doc.createElement('name')
            title_text = doc.createTextNode(line[0])
            title.appendChild(title_text)
            object.appendChild(title)
            bndbox = doc.createElement('bndbox')
            object.appendChild(bndbox)
            title = doc.createElement('xmin')
            title_text = doc.createTextNode(str(int(float(line[4]))))
            title.appendChild(title_text)
            bndbox.appendChild(title)
            title = doc.createElement('ymin')
            title_text = doc.createTextNode(str(int(float(line[5]))))
            title.appendChild(title_text)
            bndbox.appendChild(title)
            title = doc.createElement('xmax')
            title_text = doc.createTextNode(str(int(float(line[6]))))
            title.appendChild(title_text)
            bndbox.appendChild(title)
            title = doc.createElement('ymax')
            title_text = doc.createTextNode(str(int(float(line[7]))))
            title.appendChild(title_text)
            bndbox.appendChild(title)
    # 将DOM对象doc写入文件
    # 有用的部分!!!!
    # 保存xml文件的位置
    f = open('../KITTI/test/'+name+'.xml','w')
    f.write(doc.toprettyxml(indent = ''))
    f.close()
if __name__ == '__main__':
    class_ind=( 'Truck', 'Tram', 'Car', 'Van')
    cur_dir=os.getcwd()
    labels_dir=os.path.join(cur_dir,'../KITTI/labels')
    for parent, dirnames, filenames in os.walk(labels_dir): # 分别得到根目录,子目录和根目录下文件
        for file_name in filenames:
            full_path=os.path.join(parent, file_name) # 获取文件全路径
            f=open(full_path)
            split_lines = f.readlines()
            name= file_name[:-4] # 后四位是扩展名.txt,只取前面的文件名
            img_name=name+'.png'
            img_path=os.path.join('../KITTI/image',img_name) # 路径需要自行修改,但好像没什么用
            img_size=cv2.imread(img_path).shape
            generate_xml(name,split_lines,img_size,class_ind)
print('all txts has converted into xmls')

KITTY2YOLO3.py(转txt+分配)
#https://blog.csdn.net/weixin_54678439/article/details/137468288?ops_request_misc=&request_id=&biz_id=102&utm_term=kitti%E8%BD%ACyolo&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-2-137468288.142^v100^pc_search_result_base3&spm=1018.2226.3001.4187
#  xml_to_txt_yolo.py
import xml.etree.ElementTree as ET
import os
import shutil
import random

xml_file_path = 'E:/yolov5-v7.0s/KITTI/test/'  # 检查和自己的xml文件夹名称是否一致
images_file_path = 'E:/yolov5-v7.0s/KITTI/image/'  # 检查和自己的kitti图像文件夹名称是否一致
# 改成自己的类别名称
classes = ['Truck', 'Tram', 'Car', 'Van']
# 数据集划分比例,训练集80%,验证集10%,测试集10%
train_percent = 0.8
val_percent = 0.2
# test_percent = 0.1
# 此处不要改动,只是创一个临时文件夹
# 是已经转化好的txt
if not os.path.exists('temp_labels/'):
    os.makedirs('temp_labels/')
txt_file_path = 'temp_labels/'


def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return x, y, w, h


def convert_annotations(image_name):
    in_file = open(xml_file_path + image_name + '.xml')
    out_file = open(txt_file_path + image_name + '.txt', 'w')
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
    for obj in root.iter('object'):
        # difficult = obj.find('difficult').text
        cls = obj.find('name').text
        # if cls not in classes or int(difficult) == 1:
        #     continue
        if cls not in classes == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text),
             float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


total_xml = os.listdir(xml_file_path)
num_xml = len(total_xml)  # XML文件总数

for i in range(num_xml):
    name = total_xml[i][:-4]
    convert_annotations(name)


# *********************************************** #
#  parent folder
#  --data
#  ----images
#       ----train
#       ----val
#       ----test
#  ----labels
#       ----train
#       ----val
#       ----test
def create_dir():
    if not os.path.exists('images/'):
        os.makedirs('images/')
    if not os.path.exists('labels/'):
        os.makedirs('labels/')
    if not os.path.exists('images/train'):
        os.makedirs('images/train')
    if not os.path.exists('images/val'):
        os.makedirs('images/val')
    if not os.path.exists('images/test'):
        os.makedirs('images/test/')
    if not os.path.exists('labels/train'):
        os.makedirs('labels/train')
    if not os.path.exists('labels/val'):
        os.makedirs('labels/val')
    if not os.path.exists('labels/test'):
        os.makedirs('labels/test')

    return


# *********************************************** #
# 读取所有的txt文件
create_dir()
total_txt = os.listdir(txt_file_path)
num_txt = len(total_txt)
list_all_txt = range(num_txt)  # 范围 range(0, num)

num_train = int(num_txt * train_percent)
num_val = int(num_txt * val_percent)
num_test = num_txt - num_train - num_val

train = random.sample(list_all_txt, num_train)
# train从list_all_txt取出num_train个元素
# 所以list_all_txt列表只剩下了这些元素:val_test
val_test = [i for i in list_all_txt if not i in train]
# 再从val_test取出num_val个元素,val_test剩下的元素就是test
val = random.sample(val_test, num_val)
# 检查两个列表元素是否有重合的元素
# set_c = set(val_test) & set(val)
# list_c = list(set_c)
# print(list_c)
# print(len(list_c))

print("训练集数目:{}, 验证集数目:{},测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))
for i in list_all_txt:
    name = total_txt[i][:-4]

    srcImage = images_file_path + name + '.png'
    srcLabel = txt_file_path + name + '.txt'
	# 可以改一下dst后面的的路径,目前是直接在py文件所在路径创建新文件夹
    if i in train:
        dst_train_Image = 'images/train/' + name + '.png'
        dst_train_Label = 'labels/train/' + name + '.txt'
        shutil.copyfile(srcImage, dst_train_Image)
        shutil.copyfile(srcLabel, dst_train_Label)
    elif i in val:
        dst_val_Image = 'images/val/' + name + '.png'
        dst_val_Label = 'labels/val/' + name + '.txt'
        shutil.copyfile(srcImage, dst_val_Image)
        shutil.copyfile(srcLabel, dst_val_Label)
    else:
        dst_test_Image = 'images/test/' + name + '.png'
        dst_test_Label = 'labels/test/' + name + '.txt'
        shutil.copyfile(srcImage, dst_test_Image)
        shutil.copyfile(srcLabel, dst_test_Label)
print("complete")

Python 模块报错

error:Could not build wheels for opencv-python, pycocotools, opencv-python-headless, which is required to install pyproject.toml-based projects

opencv:需要对应python版本
python查询https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/

split3

1.DLL load failed while importing _sqlite3:

去官网下载对应的文件,将里面的.def和.dll放到对应环境的DLLs文件夹下
在这里插入图片描述

2. ImportError: DLL load failed while importing _sqlite3: %1 不是有效的 Win32 应用程序。

版本错误,检查下载版本是否正确(我是x64却安了x86)

BIFPN增加(yolov5.7)

增加BIFPN
总结:

  • yolov5.7有智能优化,可以不更改train.py相关
  • 需要修改部分:model中yaml文件head部分,commmon.py增加模块
  • 修改yolo.py观察模型是否正确

注意力机制相关问题

添加CBAM报错:Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass RuntimeError: adaptive_max_pool2d_backward_cuda does not have a deterministic implementation, but you set ‘torch.use_deterministic_algorithms(True)’. You can turn off determinism just for this operation, or you can use the ‘warn_only=True’ option, if that’s acceptable for your application. You can also file an issue at https://github.com/pytorch/pytorch/issues to help us prioritize adding deterministic support for this operation.

原因图

http://t.csdnimg.cn/fhmTZ
更改train.py

init_seeds(opt.seed + 1 + RANK, deterministic=True)
init_seeds(opt.seed + 1 + RANK, deterministic=False)
  • 是否影响:?
    fitting code:
根据您提供的错误信息,似乎是由于使用了adaptive_max_pool2d_backward_cuda操作且设置了'torch.use_deterministic_algorithms(True)'导致了运行时错误。该操作没有一个确定性的实现,但您设置了确定性算法的使用。错误信息还提供了一些解决方案,包括针对这个操作关闭确定性,使用'warn_only=True'选项,或者提交问题报告以协助PyTorch团队优先处理该操作的确定性支持。
为了解决这个问题,您可以考虑按照错误信息中提出的建议来进行操作。首先,您可以尝试关闭确定性算法或添加'warn_only=True'选项,这将允许您在不影响应用程序的情况下进行操作。其次,您还可以考虑向PyTorch团队提交问题报告,帮助他们更好地支持这个操作的确定性实现。

yolov5 热力图可视化

代码:
pip install grad-cam
http://t.csdnimg.cn/YgT7l
将np.int修改为了int可正常运行
下面是修改后的代码(把魔傀面具给的注释掉了)

# pip install grad-cam -i https://pypi.tuna.tsinghua.edu.cn/simple
import warnings

warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')
import torch, yaml, cv2, os, shutil
import numpy as np

np.random.seed(0)
import matplotlib.pyplot as plt
from tqdm import trange
from PIL import Image
from models.yoloTrain import Model
from utils.general import intersect_dicts
from utils.augmentations import letterbox
from utils.general import xywh2xyxy
from pytorch_grad_cam import GradCAMPlusPlus, GradCAM, XGradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
from pytorch_grad_cam.activations_and_gradients import ActivationsAndGradients


class yolov5_heatmap:
    def __init__(self, weight, cfg, device, method, layer, backward_type, conf_threshold, genCAMNum
    
                ):
        device = torch.device(device)
        ckpt = torch.load(weight)
        model_names = ckpt['model'].names
        csd = ckpt['model'].float().state_dict()  # checkpoint state_dict as FP32
        model = Model(cfg, ch=3, nc=len(model_names)).to(device)
        csd = intersect_dicts(csd, model.state_dict(), exclude=['anchor'])  # intersect
        model.load_state_dict(csd, strict=False)  # load
        model.eval()
        print(f'Transferred {len(csd)}/{len(model.state_dict())} items')

        target_layers = [eval(layer)]
        method = eval(method)
        #np.int->int
        colors = np.random.uniform(0, 255, size=(len(model_names), 3)).astype(int)
        self.__dict__.update(locals())

    def post_process(self, result):
        logits_ = result[..., 4:]
        boxes_ = result[..., :4]
        # 对socre进行排序,获取排序后索引列表
        sorted, indices = torch.sort(logits_[..., 0], descending=True)
        return logits_[0][indices[0]], xywh2xyxy(boxes_[0][indices[0]]).cpu().detach().numpy()

    def draw_detections(self, box, color, name, img):
        xmin, ymin, xmax, ymax = list(map(int, list(box)))
        cv2.rectangle(img, (xmin, ymin), (xmax, ymax), tuple(int(x) for x in color), 2)
        cv2.putText(img, str(name), (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, tuple(int(x) for x in color), 2,
                    lineType=cv2.LINE_AA)
        return img

    def __call__(self, img_path, save_path):
        # remove dir if exist
        if os.path.exists(save_path):
            shutil.rmtree(save_path)
        # make dir if not exist
        os.makedirs(save_path, exist_ok=True)

        # img process
        img = cv2.imread(img_path)
        img = letterbox(img)[0]
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = np.float32(img) / 255.0
        tensor = torch.from_numpy(np.transpose(img, axes=[2, 0, 1])).unsqueeze(0).to(self.device)

        # init ActivationsAndGradients
        grads = ActivationsAndGradients(self.model, self.target_layers, reshape_transform=None)

        # get ActivationsAndResult
        result = grads(tensor)
        activations = grads.activations[0].cpu().detach().numpy()

        # postprocess to yolo output
        post_result, post_boxes = self.post_process(result[0])


        for i in trange(self.genCAMNum):
            # if post_result[i][0] < self.conf_threshold:
            #     break

            self.model.zero_grad()
            if self.backward_type == 'conf':
                post_result[i, 0].backward(retain_graph=True)
            else:
                # get max probability for this prediction
                score = post_result[i, 1:].max()
                score.backward(retain_graph=True)

            # process heatmap
            gradients = grads.gradients[0]
            b, k, u, v = gradients.size()
            weights = self.method.get_cam_weights(self.method, None, None, None, activations,
                                                  gradients.detach().numpy())
            weights = weights.reshape((b, k, 1, 1))
            saliency_map = np.sum(weights * activations, axis=1)
            saliency_map = np.squeeze(np.maximum(saliency_map, 0))
            saliency_map = cv2.resize(saliency_map, (tensor.size(3), tensor.size(2)))
            saliency_map_min, saliency_map_max = saliency_map.min(), saliency_map.max()
            if (saliency_map_max - saliency_map_min) == 0:
                continue
            saliency_map = (saliency_map - saliency_map_min) / (saliency_map_max - saliency_map_min)

            # add heatmap and box to image
            cam_image = show_cam_on_image(img.copy(), saliency_map, use_rgb=True)
            cam_image = self.draw_detections(post_boxes[i], self.colors[int(post_result[i, 1:].argmax())],
                                             f'{self.model_names[int(post_result[i, 1:].argmax())]} {post_result[i][0]:.2f}',
                                             cam_image)
            cam_image = Image.fromarray(cam_image)
            cam_image.save(f'{save_path}/{i}.png')


def get_params():
    params = {
        'weight': 'runs2/train/exp_U2ESIM1/weights/best.pt',  # 自己训练的模型权重
        'cfg': 'models/yolov5s-SimAM.yaml',  # 模型对应配置文件
        'device': 'cpu',  # 设备
        'method': 'XGradCAM',  # 生成热力图方法GradCAMPlusPlus, GradCAM, XGradCAM
        'layer': 'model.model[]',  # 对那一层进行可视化,一般倒数第二层较佳
        'backward_type': 'conf',  # class or conf
        'conf_threshold': 0.1,  # 置信度阈值,被我注释了
        'genCAMNum': 10 , # 生成热力图张数。(保存时,按模型输出预测得分从高到低排序保存)
        # 'ratio': 0.02, # 0.02-0.1
        # 'show_box': False,
        # 'renormalize': True
    }
    return params


if __name__ == '__main__':
    model = yolov5_heatmap(**get_params())
    # 预测图像,保存文件夹路径
    model('data/images/MVI_40752__img00360.jpg', 'result')

# import warnings
# warnings.filterwarnings('ignore')
# warnings.simplefilter('ignore')
# import torch, yaml, cv2, os, shutil
# import numpy as np
# np.random.seed(0)
# import matplotlib.pyplot as plt
# from tqdm import trange
# from PIL import Image
# from models.yolo import Model
# from utils.general import intersect_dicts
# from utils.augmentations import letterbox
# from utils.general import xywh2xyxy, non_max_suppression
# from models.experimental import attempt_load
# from pytorch_grad_cam import GradCAMPlusPlus, GradCAM, XGradCAM, EigenCAM, HiResCAM, LayerCAM, RandomCAM, EigenGradCAM
# from pytorch_grad_cam.utils.image import show_cam_on_image, scale_cam_image
# from pytorch_grad_cam.activations_and_gradients import ActivationsAndGradients

# class ActivationsAndGradients:
#     """ Class for extracting activations and
#     registering gradients from targetted intermediate layers """

#     def __init__(self, model, target_layers, reshape_transform):
#         self.model = model
#         self.gradients = []
#         self.activations = []
#         self.reshape_transform = reshape_transform
#         self.handles = []
#         for target_layer in target_layers:
#             self.handles.append(
#                 target_layer.register_forward_hook(self.save_activation))
#             # Because of https://github.com/pytorch/pytorch/issues/61519,
#             # we don't use backward hook to record gradients.
#             self.handles.append(
#                 target_layer.register_forward_hook(self.save_gradient))

#     def save_activation(self, module, input, output):
#         activation = output

#         if self.reshape_transform is not None:
#             activation = self.reshape_transform(activation)
#         self.activations.append(activation.cpu().detach())

#     def save_gradient(self, module, input, output):
#         if not hasattr(output, "requires_grad") or not output.requires_grad:
#             # You can only register hooks on tensor requires grad.
#             return

#         # Gradients are computed in reverse order
#         def _store_grad(grad):
#             if self.reshape_transform is not None:
#                 grad = self.reshape_transform(grad)
#             self.gradients = [grad.cpu().detach()] + self.gradients

#         output.register_hook(_store_grad)

#     def post_process(self, result):
#         logits_ = result[..., 4:]
#         boxes_ = result[..., :4]
#         sorted, indices = torch.sort(logits_[..., 0], descending=True)
#         return logits_[0][indices[0]], xywh2xyxy(boxes_[0][indices[0]]).cpu().detach().numpy()
  
#     def __call__(self, x):
#         self.gradients = []
#         self.activations = []
#         model_output = self.model(x)
#         post_result, pre_post_boxes = self.post_process(model_output[0])
#         return [[post_result, pre_post_boxes]]

#     def release(self):
#         for handle in self.handles:
#             handle.remove()

# class yolov5_target(torch.nn.Module):
#     def __init__(self, ouput_type, conf, ratio) -> None:
#         super().__init__()
#         self.ouput_type = ouput_type
#         self.conf = conf
#         self.ratio = ratio
    
#     def forward(self, data):
#         post_result, pre_post_boxes = data
#         result = []
#         for i in trange(int(post_result.size(0) * self.ratio)):
#             if float(post_result[i, 1:].max()) < self.conf:
#                 break
#             if self.ouput_type == 'class' or self.ouput_type == 'all':
#                 result.append(post_result[i, 1:].max())
#             elif self.ouput_type == 'box' or self.ouput_type == 'all':
#                 for j in range(4):
#                     result.append(pre_post_boxes[i, j])
#         return sum(result)

# class yolov5_heatmap:
#     def __init__(self, weight, device, method, layer, backward_type, conf_threshold, ratio, show_box, renormalize):
#         device = torch.device(device)
#         ckpt = torch.load(weight)
#         model_names = ckpt['model'].names
#         model = attempt_load(weight, device=device)
#         for p in model.parameters():
#             p.requires_grad_(True)
#         model.eval()
        
#         target = yolov5_target(backward_type, conf_threshold, ratio)
#         target_layers = [model.model[l] for l in layer]
#         method = eval(method)(model, target_layers, use_cuda=device.type == 'cuda')
#         method.activations_and_grads = ActivationsAndGradients(model, target_layers, None)

#         colors = np.random.uniform(0, 255, size=(len(model_names), 3)).astype(np.int)
#         self.__dict__.update(locals())

#     def post_process(self, result):
#         result = non_max_suppression(result, conf_thres=self.conf_threshold, iou_thres=0.65)[0]
#         return result
    
#     def draw_detections(self, box, color, name, img):
#         xmin, ymin, xmax, ymax = list(map(int, list(box)))
#         cv2.rectangle(img, (xmin, ymin), (xmax, ymax), tuple(int(x) for x in color), 2)
#         cv2.putText(img, str(name), (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, tuple(int(x) for x in color), 2, lineType=cv2.LINE_AA)
#         return img

#     def renormalize_cam_in_bounding_boxes(self, boxes, image_float_np, grayscale_cam):
#         """Normalize the CAM to be in the range [0, 1] 
#         inside every bounding boxes, and zero outside of the bounding boxes. """
#         renormalized_cam = np.zeros(grayscale_cam.shape, dtype=np.float32)
#         for x1, y1, x2, y2 in boxes:
#             x1, y1 = max(x1, 0), max(y1, 0)
#             x2, y2 = min(grayscale_cam.shape[1] - 1, x2), min(grayscale_cam.shape[0] - 1, y2)
#             renormalized_cam[y1:y2, x1:x2] = scale_cam_image(grayscale_cam[y1:y2, x1:x2].copy())    
#         renormalized_cam = scale_cam_image(renormalized_cam)
#         eigencam_image_renormalized = show_cam_on_image(image_float_np, renormalized_cam, use_rgb=True)
#         return eigencam_image_renormalized
    
#     def process(self, img_path, save_path):
#         # img process
#         img = cv2.imread(img_path)
#         img = letterbox(img)[0]
#         img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#         img = np.float32(img) / 255.0
#         tensor = torch.from_numpy(np.transpose(img, axes=[2, 0, 1])).unsqueeze(0).to(self.device)
        
#         try:
#             grayscale_cam = self.method(tensor, [self.target])
#         except AttributeError as e:
#             return
        
#         grayscale_cam = grayscale_cam[0, :]
#         cam_image = show_cam_on_image(img, grayscale_cam, use_rgb=True)
        
#         with torch.no_grad():
#             pred = self.model(tensor)[0]
#             pred = self.post_process(pred)
#         if self.renormalize:
#             cam_image = self.renormalize_cam_in_bounding_boxes(pred[:, :4].cpu().detach().numpy().astype(np.int32), img, grayscale_cam)
#         if self.show_box:
#             for data in pred:
#                 data = data.cpu().detach().numpy()
#                 cam_image = self.draw_detections(data[:4], self.colors[int(data[5])], f'{self.model_names[int(data[5])]} {float(data[4]):.2f}', cam_image)
        
#         cam_image = Image.fromarray(cam_image)
#         cam_image.save(save_path)
    
#     def __call__(self, img_path, save_path):
#         # remove dir if exist
#         if os.path.exists(save_path):
#             shutil.rmtree(save_path)
#         # make dir if not exist
#         os.makedirs(save_path, exist_ok=True)

#         if os.path.isdir(img_path):
#             for img_path_ in os.listdir(img_path):
#                 self.process(f'{img_path}/{img_path_}', f'{save_path}/{img_path_}')
#         else:
#             self.process(img_path, f'{save_path}/result.png')

# def get_params():
#     params = {
#         'weight': 'runs2/train/exp_U2ESIM1/weights/best.pt',
#         'device': 'cuda:0',
#         'method': 'XGradCAM', # GradCAMPlusPlus, GradCAM, XGradCAM, EigenCAM, HiResCAM, LayerCAM, RandomCAM, EigenGradCAM
#         'layer': [16, 19, 21],
#         'backward_type': 'all', # class, box, all
#         'conf_threshold': 0.2, # 0.6
#         'ratio': 0.02, # 0.02-0.1
#         'show_box': False,
#         'renormalize': True
#     }
#     return params

# if __name__ == '__main__':
#     model = yolov5_heatmap(**get_params())
#     model(r'/home/hjj/Desktop/dataset/dataset_crowdhuman/images/test', 'result')

AttributeError: module ‘cv2’ has no attribute ‘setNumThreads’

原链接
什么时候弹出:引用模型的时候(YOLO/torch.hub)
原因:过高版本的opencv-python
->没有该函数
-》可卸载后降版本

pip install opencv-python==4.6.0.66

跳转用模块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值