2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

一种基于目标检测实现黑花屏分类任务的方案

  • 2021-05-05
  • 本文字数:4201 字

    阅读完需:约 14 分钟

一种基于目标检测实现黑花屏分类任务的方案

视频帧的黑、花屏的检测是视频质量检测中比较重要的一部分,传统做法是由测试人员通过肉眼来判断视频中是否有黑、花屏的现象,这种方式不仅耗费人力且效率较低。为了进一步节省人力、提高效率,一种自动的检测方法是大家所期待的。目前,通过分类网络模型对视频帧进行分类来自动检测是否有黑、花屏是比较可行且高效的。然而,在项目过程中,视频帧数据的收集比较困难,数据量较少,部分花屏和正常屏之间差异不够明显,导致常用的分类算法难以满足项目对分类准确度的要求。因此本文尝试了一种利用目标检测算法实现分类的方式,帮助改善单纯的分类的算法效果不够理想的问题。

核心技术与架构图

一般分类任务的流程如下图,首先需要收集数据,构成数据集;并为每一类数据定义一个类型标签,例如:0、1、2;再选择一个合适的分类网络进行分类模型的训练,图像分类的网络有很多,常见的有 VggNet, ResNet,DenseNet 等;最后用训练好的模型对新的数据进行预测,输出新数据的类别。



目标检测任务的流程不同于分类任务,其在定义类别标签的时候还需要对目标位置进行标注;目标检测的方法也有很多,例如 Fast R-CNN, SSD,YOLO 等;模型训练的中间过程也比分类模型要复杂,其输出一般为目标的位置、目标置信度以及分类结果。



由于分类算法依赖于一定量的数据,在项目实践中,数据量较少或图像类间差异较小时,传统分类算法效果不一定能满足项目需求。这时,不妨考虑用目标检测的方式来做‘分类’。接下来以 Yolov5 为例来介绍如何将目标检测框架用于实现单纯的分类任务。

技术实现

除了分类之外,目标检测还可以从自然图像中的大量预定义类别中识别出目标实例的位置。大家可能会考虑目标检测模型用于分类是不是过于繁琐或者用目标检测框架来做单纯的分类对代码的修改比较复杂。这里,我们将用一种非常简单的方式直接在数据标注和输出内容上稍作修改就能实现单纯的分类了。接下来将介绍一下具体实现方法:

数据的标注

实现目标检测时,需要对数据中的目标进行标注,这一过程是十分繁琐的。但在用于纯粹的分类上可以将这一繁琐过程简单化,无需手动标注,直接将整张图作为我们的目标,目标中心也就是图像的中心点。只需读取整张图像,获得其长、宽以及中心点的坐标就可以完成标注了。并定义好类别标签,正常屏为 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
复制代码

训练过程

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


# 加载数据,获取训练集、测试集图片路径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()
复制代码

损失的计算

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


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()
复制代码

对输出内容的处理

进行预测时,会得到所有检测到的目标的位置(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 的分类效果会更好一些。当我们在做图像分类任务时,纯粹的分类算法不能达到想要的效果时,不妨尝试一下用目标检测框架来分类吧!虽然过程稍微复杂一些,但可能会有不错的效果。目前目标检测框架有很多,用它们完成分类任务的处理方式大致和本文所描述的类似,可以根据数据集的特征选择合适目标检测架构来实现分类。本文主要介绍了如何将现有的目标检测框架直接用于单纯的图像分类任务,当然,为了使得结构更简洁,也可以将目标检测中的分类网络提取出来用于分类。


本文转载自:360 技术(ID:qihoo_tech)

原文链接:一种基于目标检测实现黑花屏分类任务的方案

2021-05-05 07:002906

评论

发布
暂无评论
发现更多内容

MySQL如何实现万亿级数据存储?

冰河

MySQL 分布式 微服务 高可用 mycat

彻底搞懂 IO 底层原理

vivo互联网技术

Java Netty 服务器 语法

Web前端如何实现断点续传

QiLab

Web 断点续传 upload pl

在线K歌的发展和优势

anyRTC开发者

音视频 WebRTC RTC sdk

申通快递 双11 云原生应用实践

阿里巴巴云原生

阿里云 Kubernetes 运维 云原生 监控

架构师训练营第 1 期 - 第 9 周 - 学习总结

wgl

极客大学架构师训练营

市值管理机器人、自动跑k线机器人开发

t13823115967

市值管理机器人 自动跑k线机器人开发

LeetCode题解:169. 多数元素,分治,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

【JAVA】List转换为array

笑春风

马士兵最新2020涵盖P5—P8Java全栈架构师学习路线,跟着老师学我已拿P7Offer!

Java架构追梦

Java 学习 架构 面试 马士兵

我是面试官,我来分享一波面经!看看我的内心OS

比伯

Java 编程 架构 面试 技术宅

视频作品播放量低:自媒体作者如何走出新手村

石头IT视角

《华为数据之道》读书笔记:第 2 章 建立企业级数据综合治理体系

方志

数据中台 数据仓库 数字化转型 数据治理

第一周 架构方法 作业一 「架构师训练营 3 期」

胡云飞

极客大学架构师训练营 架构方法

甲方日常 56

句子

工作 随笔杂谈 日常

面试JVM一问三不知??来看看这个

程序员的时光

JVM Java虚拟机

30分钟开发一款抓取网站图片资源的浏览器插件

徐小夕

Java chrome 大前端 chrome扩展

如何基于App SDK快速地开发一个IoT App?

IoT云工坊

App 物联网 sdk 智能家居

区块链应用场景有哪些?区块链应用开发

t13823115967

区块链应用场景有哪些 区块链应用开发

【薪火计划】05 - 坦诚是领导力的根基

码字与律动

管理

Python进阶——什么是元类?

Kaito

Python

大厂经验:埋点数据质量之埋点验证

阿亮

埋点 数据验证

他在滕王阁上醒来,见到智慧视觉第一城

脑极体

moon不讲武德!!!一个类加载机制给面试官说蒙了!!

moon聊技术

Java JVM 类加载 类加载器

面试专题-Java基础面试技术

码界西柚

英特尔与南京溧水经济技术开发区共同成立智能交通研究院

E科讯

双指针算法和位运算&离散化和区间合并

落曦

基于DAYU的实时作业开发,分分钟搭建企业个性化推荐平台

华为云开发者联盟

华为 算法 数据 dayu

Appium上下文和H5测试(一)

清菡软件测试

App

About Me

翎君

android

云原生应用Go语言:你还在考虑的时候,别人已经应用实践

华为云开发者联盟

微服务 云技术 Go 语言

一种基于目标检测实现黑花屏分类任务的方案_架构_360技术_InfoQ精选文章