python目标检测实现黑花屏分类任务示例

目录
  • 背景
  • 核心技术与架构图
  • 技术实现
    • 1.数据的标注
    • 2.训练过程
    • 3.损失的计算
    • 4.对输出内容的处理
  • 效果展示
  • 总结

背景

视频帧的黑、花屏的检测是视频质量检测中比较重要的一部分,传统做法是由测试人员通过肉眼来判断视频中是否有黑、花屏的现象,这种方式不仅耗费人力且效率较低。

为了进一步节省人力、提高效率,一种自动的检测方法是大家所期待的。目前,通过分类网络模型对视频帧进行分类来自动检测是否有黑、花屏是比较可行且高效的。

然而,在项目过程中,视频帧数据的收集比较困难,数据量较少,部分花屏和正常屏之间差异不够明显,导致常用的分类算法难以满足项目对分类准确度的要求。

因此本文尝试了一种利用目标检测算法实现分类的方式,帮助改善单纯的分类的算法效果不够理想的问题。

核心技术与架构图

一般分类任务的流程如下图,首先需要收集数据,构成数据集;

并为每一类数据定义一个类型标签,例如:0、1、2;再选择一个合适的分类网络进行分类模型的训练,图像分类的网络有很多,常见的有 VggNet, ResNet,DenseNet 等;

最后用训练好的模型对新的数据进行预测,输出新数据的类别。

目标检测任务的流程不同于分类任务,其在定义类别标签的时候还需要对目标位置进行标注;

目标检测的方法也有很多,例如 Fast R-CNN, SSD,YOLO 等;

模型训练的中间过程也比分类模型要复杂,其输出一般为目标的位置、目标置信度以及分类结果。

由于分类算法依赖于一定量的数据,在项目实践中,数据量较少或图像类间差异较小时,传统分类算法效果不一定能满足项目需求。这时,不妨考虑用目标检测的方式来做 ‘分类’。

接下来以 Yolov5 为例来介绍如何将目标检测框架用于实现单纯的分类任务。

技术实现

除了分类之外,目标检测还可以从自然图像中的大量预定义类别中识别出目标实例的位置。

大家可能会考虑目标检测模型用于分类是不是过于繁琐或者用目标检测框架来做单纯的分类对代码的修改比较复杂。

这里,我们将用一种非常简单的方式直接在数据标注和输出内容上稍作修改就能实现单纯的分类了。接下来将介绍一下具体实现方法:

1.数据的标注

实现目标检测时,需要对数据中的目标进行标注,这一过程是十分繁琐的。但在用于纯粹的分类上可以将这一繁琐过程简单化,无需手动标注,直接将整张图作为我们的目标,目标中心也就是图像的中心点。

只需读取整张图像,获得其长、宽以及中心点的坐标就可以完成标注了。并定义好类别标签,正常屏为 0,花屏为:1,黑屏为 2。具体实现如下:

OBJECT_DICT = {"Normalscreen": 0, "Colorfulscreen": 1, "Blackscreen": 2}
def parse_json_file(image_path):
    imageName = os.path.basename(image_path).split('.')[0]
    img = cv2.imread(image_path)
    size = img.shape
    label = image_path.split('/')[4].split('\\')[0]
    label = OBJECT_DICT.get(label)
    imageWidth = size[0]
    imageHeight = size[1]
    label_dict = {}
    xmin, ymin = (0, 0)
    xmax, ymax = (imageWidth, imageHeight)
    xcenter = (xmin + xmax) / 2
    xcenter = xcenter / float(imageWidth)
    ycenter = (ymin + ymax) / 2
    ycenter = ycenter / float(imageHeight)
    width = ((xmax - xmin) / float(imageWidth))
    heigt = ((ymax - ymin) / float(imageHeight))
    label_dict.update({label: [str(xcenter), str(ycenter), str(width), str(heigt)]})
    label_dict = sorted(label_dict.items(), key=lambda x: x[0])
    return imageName, label_dict

2.训练过程

该过程与目标检测的训练过程一致,不需要进行大的修改,只需要根据数据集的特性对参数进行调整。

# 加载数据,获取训练集、测试集图片路径
with open(opt.data) as f:
    data_dict = yaml.load(f, Loader=yaml.FullLoader)
    with torch_distributed_zero_first(rank):
        check_dataset(data_dict)
train_path = data_dict['train']
test_path = data_dict['val']
Number_class, names = (1, ['item']) if opt.single_cls else (int(data_dict['nc']), data_dict['names'])
# 创建模型
model = Model(opt.cfg, ch=3, nc=Number_class).to(device)
# 学习率的设置
lf = lambda x: ((1 + math.cos(x * math.pi / epochs)) / 2) * (1 - hyp['lrf']) + hyp['lrf']
scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)
# 训练
for epoch in range(start_epoch, epochs):
model.train()

3.损失的计算

损失由三部分组成,边框损失,目标损失,分类损失,具体如下:

def compute_loss(p, targets, model):
    device = targets.device
    loss_cls, loss_box, loss_obj = torch.zeros(1, device=device), torch.zeros(1, device=device), torch.zeros(1, device=device)
    tcls, tbox, indices, anchors = build_targets(p, targets, model)
h = model.hyp
    # 定义损失函数
    BCEcls = nn.BCEWithLogitsLoss(pos_weight=torch.Tensor([h['cls_pw']])).to(device)
    BCEobj = nn.BCEWithLogitsLoss(pos_weight=torch.Tensor([h['obj_pw']])).to(device)
    cp, cn = smooth_BCE(eps=0.0)
    # 损失
    nt = 0
    np = len(p)
    balance = [4.0, 1.0, 0.4] if np == 3 else [4.0, 1.0, 0.4, 0.1]
for i, pi in enumerate(p):
        image, anchor, gridy, gridx = indices[i]
        tobj = torch.zeros_like(pi[..., 0], device=device)
        n = image.shape[0]
        if n:
            nt += n  # 计算目标
            ps = pi[anchor, image, gridy, gridx]
            pxy = ps[:, :2].sigmoid() * 2. - 0.5
            pwh = (ps[:, 2:4].sigmoid() * 2) ** 2 * anchors[i]
            predicted_box = torch.cat((pxy, pwh), 1).to(device)                    giou = bbox_iou(predicted_box.T, tbox[i], x1y1x2y2=False, CIoU=True)
       loss_box += (1.0 - giou).mean()
            tobj[image, anchor, gridy, gridx] = (1.0 - model.gr) + model.gr *   giou.detach().clamp(0).type(tobj.dtype)
            if model.nc > 1:
                t = torch.full_like(ps[:, 5:], cn, device=device)
                t[range(n), tcls[i]] = cp
                loss_cls += BCEcls(ps[:, 5:], t)
        loss_obj += BCEobj(pi[..., 4], tobj) * balance[i]
    s = 3 / np
    loss_box *= h['giou'] * s
    loss_obj *= h['obj'] * s * (1.4 if np == 4 else 1.)
    loss_cls *= h['cls'] * s
    bs = tobj.shape[0]
    loss = loss_box + loss_obj + loss_cls
    return loss * bs, torch.cat((loss_box, loss_obj, loss_cls, loss)).detach()

4.对输出内容的处理

进行预测时,会得到所有检测到的目标的位置(x,y,w,h),objectness 置信度和分类结果。由于最终目的是对整张图进行分类,可以忽略位置信息,重点考虑置信度和分类结果:将检测到的目标类别作为分类结果,如果同时检测出多个目标,可以将置信度最大的目标的类别作为分类结果。代码如下:

def detect(opt,img):
    out, source, weights, view_img, save_txt, imgsz = \
        opt.output, img, opt.weights, opt.view_img, opt.save_txt, opt.img_size
    device = select_device(opt.device)
    half = device.type != 'cpu'
    model = experimental.attempt_load(weights, map_location=device)
    imgsz = check_img_size(imgsz, s=model.stride.max())
    if half:
        model.half()
    img = letterbox(img)[0]
    img = img[:, :, ::-1].transpose(2, 0, 1)
    img = np.ascontiguousarray(img)
    img_warm = torch.zeros((1, 3, imgsz, imgsz), device=device)
    _ = model(img_warm.half() if half else img_warm) if device.type != 'cpu' else None
    img = torch.from_numpy(img).to(device)
    img = img.half() if half else img.float()
    img /= 255.0
    if img.ndimension() == 3:
        img = img.unsqueeze(0)
    pred = model(img, augment=opt.augment)[0]
    # 应用非极大值抑制
    pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
    # 处理检测的结果
    for i, det in enumerate(pred):
        if det is not None and len(det):
            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img.shape).round()
            all_conf = det[:, 4]
            if len(det[:, -1]) > 1:
                ind = torch.max(all_conf, 0)[1]
                c = torch.take(det[:, -1], ind)
detect_class = int(c)
            else:
                for c in det[:, -1]:
                    detect_class = int(c)
            return detect_class

效果展示

为了将视频帧进行黑、花屏分类,测试人员根据经验将屏幕分为正常屏(200 张)、花屏(200 张)和黑屏(200 张)三类,其中正常屏幕标签为 0,花屏的标签为 1,黑屏的标签为 2。

为了进一步说明该方法的有效性,我们将基于 Yolov5 的 ‘分类’ 效果与 ResNet 分类效果做了对比。根据测试人员对 ResNet 分类效果的反馈来看,ResNet 模型容易将正常屏与花屏错误分类,例如,下图被测试人员定义为正常屏:

ResNet 的分类结果为 1,即为花屏,显然,这不是我们想要的结果。

基于 Yolov5 的分类结果为 0,即为正常屏,这是我们所期待的结果。

同时,通过对一批测试数据的分类效果来看,Yolov5 的分类效果比 ResNet 的分类准确度更高,ResNet 的分类准确率为 88%,而基于 Yolov5 的分类准确率高达 97%。

总结

对于较小数据集的黑、花屏的分类问题,采用 Yolov5 来实现分类相较于 ResNet 的分类效果会更好一些。当我们在做图像分类任务时,纯粹的分类算法不能达到想要的效果时,不妨尝试一下用目标检测框架来分类吧!虽然过程稍微复杂一些,但可能会有不错的效果。

目前目标检测框架有很多,用它们完成分类任务的处理方式大致和本文所描述的类似,可以根据数据集的特征选择合适目标检测架构来实现分类。

本文主要介绍了如何将现有的目标检测框架直接用于单纯的图像分类任务,当然,为了使得结构更简洁,也可以将目标检测中的分类网络提取出来用于分类,更多关于python目标检测黑花屏分类的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python人工智能之混合高斯模型运动目标检测详解分析

    [人工智能项目]混合高斯模型运动目标检测 本次工作主要对视频中运动中的人或物的边缘背景进行检测. 那么走起来瓷!!! 原视频 高斯算法提取工作 import cv2 import numpy as np # 高斯算法 class gaussian: def __init__(self): self.mean = np.zeros((1, 3)) self.covariance = 0 self.weight = 0; self.Next = None self.Previous = None c

  • Python 使用Opencv实现目标检测与识别的示例代码

    在上章节讲述到图像特征检测与匹配 ,本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: import cv2 def is_inside(o, i): ox, oy, ow, oh = o ix, iy, iw, ih = i # 如果符合条件,返回True,否则返回False return ox > ix and oy > iy and ox + ow < ix + iw and o

  • python目标检测SSD算法训练部分源码详解

    目录 学习前言 讲解构架 模型训练的流程 1.设置参数 2.读取数据集 3.建立ssd网络. 4.预处理数据集 5.框的编码 6.计算loss值 7.训练模型并保存 开始训练 学习前言 ……又看了很久的SSD算法,今天讲解一下训练部分的代码.预测部分的代码可以参照https://blog.csdn.net/weixin_44791964/article/details/102496765 讲解构架 本次教程的讲解主要是对训练部分的代码进行讲解,该部分讲解主要是对训练函数的执行过程与执行思路进行详

  • Python Opencv实现单目标检测的示例代码

    一 简介 目标检测即为在图像中找到自己感兴趣的部分,将其分割出来进行下一步操作,可避免背景的干扰.以下介绍几种基于opencv的单目标检测算法,算法总体思想先尽量将目标区域的像素值全置为1,背景区域全置为0,然后通过其它方法找到目标的外接矩形并分割,在此选择一张前景和背景相差较大的图片作为示例. 环境:python3.7 opencv4.4.0 二 背景前景分离 1 灰度+二值+形态学 轮廓特征和联通组件 根据图像前景和背景的差异进行二值化,例如有明显颜色差异的转换到HSV色彩空间进行分割. 1

  • python目标检测基于opencv实现目标追踪示例

    目录 主要代码 信息封装类 更新utils python-opencv3.0新增了一些比较有用的追踪器算法,这里根据官网示例写了一个追踪器类 程序只能运行在安装有opencv3.0以上版本和对应的contrib模块的python解释器 主要代码 #encoding=utf-8 import cv2 from items import MessageItem import time import numpy as np ''' 监视者模块,负责入侵检测,目标跟踪 ''' class WatchDo

  • Python可视化目标检测框的实现代码

    目录 1 引言 2 举个栗子 3 实现 3.1 函数讲解 3.2 读入图像 3.3 标签美化 3.4 角点美化 3.5 综合效果 4 透明效果实现 5 扩展应用 6 总结 7 参考 1 引言 随着计算机视觉算法工程师的内卷,从事目标检测的小伙伴们越来越多了. 很多时候我们费了九牛二虎之力训练了一版模型,可是可视化出来的效果平淡无奇. 是不是有点太不给力啦,作为计算机视觉工程师,我们是不是应该关注下如何优雅地可视化我们模型地检测结果呢? 2 举个栗子 最常用的可视化目标检测结果的就是我们所说的矩形

  • python目标检测实现黑花屏分类任务示例

    目录 背景 核心技术与架构图 技术实现 1.数据的标注 2.训练过程 3.损失的计算 4.对输出内容的处理 效果展示 总结 背景 视频帧的黑.花屏的检测是视频质量检测中比较重要的一部分,传统做法是由测试人员通过肉眼来判断视频中是否有黑.花屏的现象,这种方式不仅耗费人力且效率较低. 为了进一步节省人力.提高效率,一种自动的检测方法是大家所期待的.目前,通过分类网络模型对视频帧进行分类来自动检测是否有黑.花屏是比较可行且高效的. 然而,在项目过程中,视频帧数据的收集比较困难,数据量较少,部分花屏和正

  • python目标检测IOU的概念与示例

    目录 学习前言 什么是IOU IOU的特点 全部代码 学习前言 神经网络的应用还有许多,目标检测就是其中之一,目标检测中有一个很重要的概念便是IOU 什么是IOU IOU是一种评价目标检测器的一种指标. 下图是一个示例:图中绿色框为实际框(好像不是很绿……),红色框为预测框,当我们需要判断两个框之间的关系时,需要用什么指标呢? 此时便需要用到IOU. 计算IOU的公式为: 可以看到IOU是一个比值,即交并比. 在分子部分,值为预测框和实际框之间的重叠区域: 在分母部分,值为预测框和实际框所占有的

  • python目标检测SSD算法预测部分源码详解

    目录 学习前言 什么是SSD算法 ssd_vgg_300主体的源码 学习前言 ……学习了很多有关目标检测的概念呀,咕噜咕噜,可是要怎么才能进行预测呢,我看了好久的SSD源码,将其中的预测部分提取了出来,训练部分我还没看懂 什么是SSD算法 SSD是一种非常优秀的one-stage方法,one-stage算法就是目标检测和分类是同时完成的,其主要思路是均匀地在图片的不同位置进行密集抽样,抽样时可以采用不同尺度和长宽比,然后利用CNN提取特征后直接进行分类与回归,整个过程只需要一步,所以其优势是速度

  • python目标检测yolo2详解及预测代码复现

    目录 前言 实现思路 1.yolo2的预测思路(网络构建思路) 2.先验框的生成 3.利用先验框对网络的输出进行解码 4.进行得分排序与非极大抑制筛选 实现结果 前言 ……最近在学习yolo1.yolo2和yolo3,写这篇博客主要是为了让自己对yolo2的结构有更加深刻的理解,同时要理解清楚先验框的含义. 尽量配合代码观看会更容易理解. 直接下载 实现思路 1.yolo2的预测思路(网络构建思路) YOLOv2使用了一个新的分类网络DarkNet19作为特征提取部分,DarkNet19包含19

  • python目标检测yolo1 yolo2 yolo3和SSD网络结构对比

    目录 睿智的目标检测5——yolo1.yolo2.yolo3和SSD的网络结构汇总对比 学习前言各个网络的结构图与其实现代码1.yolo12.yolo23.yolo34.SSD 总结 学习前言 ……最近在学习yolo1.yolo2和yolo3,事实上它们和SSD网络有一定的相似性,我准备汇总一下,看看有什么差别. 各个网络的结构图与其实现代码 1.yolo1 由图可见,其进行了二十多次卷积还有四次最大池化,其中3x3卷积用于提取特征,1x1卷积用于压缩特征,最后将图像压缩到7x7xfilter的

  • python目标检测非极大抑制NMS与Soft-NMS

    目录 睿智的目标检测31——非极大抑制NMS与Soft-NMS 注意事项学习前言什么是非极大抑制NMS1.非极大抑制NMS的实现过程2.柔性非极大抑制Soft-NMS的实现过程 注意事项 Soft-NMS对于大多数数据集而言,作用比较小,提升效果非常不明显,它起作用的地方是大量密集的同类重叠场景,大量密集的不同类重叠场景其实也没什么作用,同学们可以借助Soft-NMS理解非极大抑制的含义,但是实现的必要性确实不强,在提升网络性能上,不建议死磕Soft-NMS. 已对该博文中的代码进行了重置,视频

  • python:目标检测模型预测准确度计算方式(基于IoU)

    训练完目标检测模型之后,需要评价其性能,在不同的阈值下的准确度是多少,有没有漏检,在这里基于IoU(Intersection over Union)来计算. 希望能提供一些思路,如果觉得有用欢迎赞我表扬我~ IoU的值可以理解为系统预测出来的框与原来图片中标记的框的重合程度.系统预测出来的框是利用目标检测模型对测试数据集进行识别得到的. 计算方法即检测结果DetectionResult与GroundTruth的交集比上它们的并集,如下图: 蓝色的框是:GroundTruth 黄色的框是:Dete

  • python目标检测给图画框,bbox画到图上并保存案例

    我就废话不多说了,还是直接上代码吧! import os import xml.dom.minidom import cv2 as cv ImgPath = 'C:/Users/49691/Desktop/gangjin/gangjin_test/JPEGImages/' AnnoPath = 'C:/Users/49691/Desktop/gangjin/gangjin_test/Annotations/' #xml文件地址 save_path = '' def draw_anchor(Img

  • python目标检测yolo3详解预测及代码复现

    目录 学习前言 实现思路 1.yolo3的预测思路(网络构建思路) 2.利用先验框对网络的输出进行解码 3.进行得分排序与非极大抑制筛选 实现结果 学习前言 对yolo2解析完了之后当然要讲讲yolo3,yolo3与yolo2的差别主要在网络的特征提取部分,实际的解码部分其实差距不大 代码下载 本次教程主要基于github中的项目点击直接下载,该项目相比于yolo3-Keras的项目更容易看懂一些,不过它的许多代码与yolo3-Keras相同. 我保留了预测部分的代码,在实际可以通过执行dete

随机推荐