【python】OpenCV—Mask RCNN for Object Detection and Instance Segmentation
文章目录
- 1、任务描述
- 2、MASR RCNN 网络结构
- 3、方法实现
- 4、结果展示
- 5、涉及到的库
- getPerfProfile
- 6、参考
1、任务描述
利用 mask rcnn 网络,进行图片和视频的目标检测和实例分割
2、MASR RCNN 网络结构
3、方法实现
# Copyright (C) 2018-2019, BigVision LLC (LearnOpenCV.com), All Rights Reserved.
# Author : Sunita Nayak
# Article : https://www.learnopencv.com/deep-learning-based-object-detection-and-instance-segmentation-using-mask-r-cnn-in-opencv-python-c/
# License: BSD-3-Clause-Attribution (Please read the license file.)
# This work is based on OpenCV samples code (https://opencv.org/license.html)import cv2 as cv
import argparse
import numpy as np
import os.path
import sys
import random# Initialize the parameters
confThreshold = 0.5 # Confidence threshold
maskThreshold = 0.3 # Mask thresholdparser = argparse.ArgumentParser(description='Use this script to run Mask-RCNN object detection and segmentation')
parser.add_argument('--image', help='Path to image file.')
parser.add_argument('--video', help='Path to video file.', default="cars.mp4")
parser.add_argument("--device", default="gpu", help="Device to inference on")
args = parser.parse_args()"""
python mask_rcnn.py --image ./images/person.jpg --device cpu
python mask_rcnn.py --video ./cars.mp4 --device cpu
"""# Draw the predicted bounding box, colorize and show the mask on the image
def drawBox(frame, classId, conf, left, top, right, bottom, classMask):# Draw a bounding box.cv.rectangle(frame, (left, top), (right, bottom), (255, 178, 50), 3)# Print a label of class.label = '%.2f' % confif classes:assert (classId < len(classes))label = '%s:%s' % (classes[classId], label) # 'person:1.00'# Display the label at the top of the bounding boxlabelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)top = max(top, labelSize[1])cv.rectangle(frame, (left, top - round(1.5 * labelSize[1])), (left + round(1.5 * labelSize[0]), top + baseLine),(255, 255, 255), cv.FILLED)cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 0), 1)# Resize the mask, threshold, color and apply it on the imageclassMask = cv.resize(classMask, (right - left + 1, bottom - top + 1))mask = (classMask > maskThreshold)roi = frame[top:bottom + 1, left:right + 1][mask]# color = colors[classId%len(colors)]# Comment the above line and uncomment the two lines below to generate different instance colorscolorIndex = random.randint(0, len(colors) - 1)color = colors[colorIndex]frame[top:bottom + 1, left:right + 1][mask] = ([0.3 * color[0], 0.3 * color[1], 0.3 * color[2]] + 0.7 * roi).astype(np.uint8)# Draw the contours on the imagemask = mask.astype(np.uint8)contours, hierarchy = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)cv.drawContours(frame[top:bottom + 1, left:right + 1], contours, -1, color, 3, cv.LINE_8, hierarchy, 100)# For each frame, extract the bounding box and mask for each detected object
def postprocess(boxes, masks):# Output size of masks is NxCxHxW where# N - number of detected boxes# C - number of classes (excluding background)# HxW - segmentation shapenumClasses = masks.shape[1] # 90numDetections = boxes.shape[2] # 100frameH = frame.shape[0] # 531frameW = frame.shape[1] # 800for i in range(numDetections): # traverse top 100 ROIbox = boxes[0, 0, i] # (1, 1, 100, 7) -> (7,)# array([0. , 0. , 0.99842095, 0.7533724 , 0.152397 , 0.92448074, 0.9131955 ], dtype=float32)mask = masks[i] # (100, 90, 15, 15) -> (90, 15, 15)score = box[2] # 0.99842095if score > confThreshold:classId = int(box[1])# Extract the bounding boxleft = int(frameW * box[3])top = int(frameH * box[4])right = int(frameW * box[5])bottom = int(frameH * box[6])left = max(0, min(left, frameW - 1))top = max(0, min(top, frameH - 1))right = max(0, min(right, frameW - 1))bottom = max(0, min(bottom, frameH - 1))# Extract the mask for the objectclassMask = mask[classId]# Draw bounding box, colorize and show the mask on the imagedrawBox(frame, classId, score, left, top, right, bottom, classMask)# Load names of classes
classesFile = "mscoco_labels.names"
classes = None"""
person
bicycle
car
motorcycle
airplane
bus
train
truck
boat
traffic light
fire hydrantstop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffebackpack
umbrellahandbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottlewine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
couch
potted plant
beddining tabletoilettv
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigeratorbook
clock
vase
scissors
teddy bear
hair drier
toothbrush
"""with open(classesFile, 'rt') as f:classes = f.read().rstrip('\n').split('\n')# Give the textGraph and weight files for the model
textGraph = "./mask_rcnn_inception_v2_coco_2018_01_28.pbtxt"
modelWeights = "./mask_rcnn_inception_v2_coco_2018_01_28/frozen_inference_graph.pb"# Load the network
net = cv.dnn.readNetFromTensorflow(modelWeights, textGraph)if args.device == "cpu":net.setPreferableBackend(cv.dnn.DNN_TARGET_CPU)print("Using CPU device")
elif args.device == "gpu":net.setPreferableBackend(cv.dnn.DNN_BACKEND_CUDA)net.setPreferableTarget(cv.dnn.DNN_TARGET_CUDA)print("Using GPU device")# Load the classes
colorsFile = "colors.txt"
with open(colorsFile, 'rt') as f:colorsStr = f.read().rstrip('\n').split('\n')# ['0 255 0', '0 0 255', '255 0 0', '0 255 255', '255 255 0', '255 0 255', '80 70 180',# '250 80 190', '245 145 50', '70 150 250', '50 190 190']colors = [] # [0,0,0]
for i in range(len(colorsStr)):rgb = colorsStr[i].split(' ')color = np.array([float(rgb[0]), float(rgb[1]), float(rgb[2])])colors.append(color)"""
[array([ 0., 255., 0.]), array([ 0., 0., 255.]), array([255., 0., 0.]), array([ 0., 255., 255.]),
array([255., 255., 0.]), array([255., 0., 255.]), array([ 80., 70., 180.]), array([250., 80., 190.]),
array([245., 145., 50.]), array([ 70., 150., 250.]), array([ 50., 190., 190.])]
"""winName = 'Mask-RCNN Object detection and Segmentation in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)outputFile = "mask_rcnn_out_py.avi"
if (args.image):# Open the image fileif not os.path.isfile(args.image):print("Input image file ", args.image, " doesn't exist")sys.exit(1)cap = cv.VideoCapture(args.image)outputFile = args.image[:-4] + '_mask_rcnn_out_py.jpg'
elif (args.video):# Open the video fileif not os.path.isfile(args.video):print("Input video file ", args.video, " doesn't exist")sys.exit(1)cap = cv.VideoCapture(args.video)outputFile = args.video[:-4] + '_mask_rcnn_out_py.avi'
else:# Webcam inputcap = cv.VideoCapture(0)# Get the video writer initialized to save the output video
if (not args.image):vid_writer = cv.VideoWriter(outputFile, cv.VideoWriter_fourcc('M', 'J', 'P', 'G'), 28,(round(cap.get(cv.CAP_PROP_FRAME_WIDTH)), round(cap.get(cv.CAP_PROP_FRAME_HEIGHT))))while cv.waitKey(1) < 0:# Get frame from the videohasFrame, frame = cap.read()# Stop the program if reached end of videoif not hasFrame:print("Done processing !!!")print("Output file is stored as ", outputFile)cv.waitKey(3000)break# Create a 4D blob from a frame.blob = cv.dnn.blobFromImage(frame, swapRB=True, crop=False) # (1, 3, 531, 800)# Set the input to the networknet.setInput(blob)# Run the forward pass to get output from the output layersboxes, masks = net.forward(['detection_out_final', 'detection_masks'])"""(1, 1, 100, 7) top 100 RoI, (0, classid, score, x0, y0, x1, y1)(100, 90, 15, 15) 100 RoI, 90 classes, 15*15 feature maps size"""# Extract the bounding box and mask for each of the detected objectspostprocess(boxes, masks)# Put efficiency information.t, _ = net.getPerfProfile()label = 'Mask-RCNN Inference time for a frame : %0.0f ms' % abs(t * 1000.0 / cv.getTickFrequency())cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))# Write the frame with the detection boxesif (args.image):cv.imwrite(outputFile, frame.astype(np.uint8));else:vid_writer.write(frame.astype(np.uint8))cv.imshow(winName, frame)
根据 bbox 的类别,取 mask 输出特征图对应类别的通道特征 classMask = mask[classId]
画 mask 的时候,先 resize 到 bbox 的大小,再借助了 cv2.findContours
和 drawContours
绘制出轮廓
4、结果展示
输入图片
输出结果
输入图片
输出结果
输入图片
输出结果
输入图片
输出结果
输入图片
输出结果
输入图片
输出结果
输入图片
输出结果
看看视频的结果
cars_mask_rcnn_out
5、涉及到的库
getPerfProfile
getPerfProfile 是 OpenCV 库中用于获取深度学习模型推理性能概况的一个函数。该函数主要用于分析模型中各层的执行时间,帮助开发者了解模型性能瓶颈和优化方向。
一、功能
getPerfProfile 函数返回一个包含模型各层执行时间的向量(或类似结构),单位通常为毫秒或秒,具体取决于函数实现和调用方式。
通过这个函数,开发者可以获取到模型推理过程中每一层所消耗的时间,进而分析哪些层是性能瓶颈,需要进一步优化。
使用场景
在使用 OpenCV 进行深度学习模型推理时,尤其是在对实时性要求较高的应用场景中,如视频处理、实时监控系统等,使用 getPerfProfile 函数可以帮助开发者评估和优化模型性能。
二、示例代码
import cv2 # 加载预训练模型
net = cv2.dnn.readNet("model.xml", "model.bin") # 假设有一个输入图像 blob
blob = cv2.dnn.blobFromImage(...) # 设置输入并进行推理
net.setInput(blob)
outputs = net.forward() # 获取性能概况
t, _ = net.getPerfProfile() # 假设 t 是以秒为单位的时间,转换为毫秒并打印
print("Inference time: %.2f ms" % (t * 1000.0)) # 如果需要更详细的每层时间,可以遍历 t
# 注意:这里的 t 可能是一个向量,包含了多层的执行时间
for layer_idx, layer_time in enumerate(t): print(f"Layer {layer_idx}: {layer_time * 1000.0} ms")
三、注意事项
getPerfProfile 函数的返回值和单位可能因 OpenCV 的不同版本或不同的深度学习后端(如 DNN 模块支持的 TensorFlow、Caffe、PyTorch 等)而有所不同。
在使用该函数时,请确保您的 OpenCV 版本支持该功能,并仔细阅读相关文档以了解其具体用法和注意事项。
由于深度学习模型的复杂性和多样性,getPerfProfile 函数提供的性能数据仅供参考,实际的优化工作还需要结合模型的具体结构和应用场景进行。
6、参考
-
论文解读
【Mask RCNN】《Mask R-CNN》 -
tensorflow 代码解读
Mask RCNN without Mask -
OpenCV进阶(7)在 OpenCV中使用 Mask RCNN实现对象检测和实例分割
相关文章:

【python】OpenCV—Mask RCNN for Object Detection and Instance Segmentation
文章目录 1、任务描述2、MASR RCNN 网络结构3、方法实现4、结果展示5、涉及到的库getPerfProfile 6、参考 1、任务描述 利用 mask rcnn 网络,进行图片和视频的目标检测和实例分割 2、MASR RCNN 网络结构 3、方法实现 # Copyright (C) 2018-2019, BigVision LLC (L…...
通过 Python 使用 Pexels图片库 API 打造个性化壁纸应用
在数字时代,照片不仅仅是回忆的载体,它们还是我们生活的美丽装饰品。想象一下,如果你能轻松地将世界上最美的免费图片应用到你的应用程序中,岂不是让你的程序立刻闪亮起来?好消息是,这不仅仅是一个梦想。今…...

多线程篇(其它容器- CopyOnWriteArrayList)(持续更新迭代)
一、CopyOnWriteArrayList(一) 1. 简介 并发包中的并发List只有CopyOnWriteArrayList。 CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行的修改操作都是在底层的一个复制的数 组(快照)上进行的࿰…...
OPENAIGC开发者大赛高校组金奖 | 知洞—基于大模型的智慧题库
在第二届拯救者杯OPENAIGC开发者大赛中,涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到,我们特意开设了优秀作品报道专栏,旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者,希望能带给您…...

java服务CPU使用率高排查
第一步 使用top命令进行查看 如果是死锁,cpu使用率不会很高,但不会响应,这时这样排查。 第二步 使用jps查看到进程id,再使用jstack pid查看线程堆栈信息 jstack pid会出现如图所示的信息,表示发生死锁,然后去排查这…...

聚焦:clicOH 借助 NVIDIA cuOpt 实现最后一英里交付速度 20 倍提升
受消费者行为转变和疫情影响,电子商务继续呈爆炸式增长和转型。因此,物流和运输公司发现自己处于包裹配送革命的前沿。这新的现实情况在最后一英里配送中尤为明显,而后者现在已经成为供应链物流中成本最高的要素,占从零售到制造等…...
从头开始嵌入式第三十八天(数据结构 双向链表)
目录 双向链表 一、结构特点 二、操作优势 三、应用场景 1.创建链表 2.头插数据 3.打印数据 4.查找数据 5.删除数据 6.更改数据 7.清空数据 8.尾插数据 9.按位插入 10.获取长度 11.是否为空 双向链表 双向链表是一种链表结构。 一、结构特点 1. 每个节点包含两个…...

chapter14-集合——(List-HashSet)——day18
目录 519-HashSet全面说明 520-数组链表模拟 521-HashSet扩容机制 重要 522-HashSet源码解读1 526-HashSet最佳实践 527-hashSet思考题 519-HashSet全面说明 题一、 两个tom都可以添加成功是因为这是两个对象 看源码做分析:不是直接指向常量池的吗?…...

企业会议室预约管理系统
基于springbootvuemysql实现的企业会议室预约管理系统(源码数据库部署视频) ### 主要技术 SpringBoot、Vue、MySQL ### 系统角色 员工、管理员 ### 系统功能 1)管理员:数据统计(会议室使用统计-柱状图、设备状态统计…...
安全API
提到安全,大部分在学习和调试编程语言时并不太在意,真正爆发问题是在用户端。真正的安全漏洞是很可怕的,获取系统最高权限,获得敏感资讯,伤心不已,泪流满面。 字符串 C语言简洁自由的风格,产生…...

【论文阅读】视觉分割新SOTA: Segment Anything(SAM)
导言 随着基于对比文本—图像对的预训练(CLIP)方法或者模型、聊天生成预训练转换器(ChatGPT)、生成预训练转换器-4(GPT-4)等基础大模型的出现,通用人工智能( AGI)的研究…...
redis之list核心命令演示与细节探索
redis之list核心命令演示与细节探索 BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout summary: Pop an element from a list, push it to another list and return it; or block until one is available since: 6.2.0 BLPOP key [key …] timeout summary: Remove …...

[数据集][目标检测]智慧农业草莓叶子病虫害检测数据集VOC+YOLO格式4040张9类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):4040 标注数量(xml文件个数):4040 标注数量(txt文件个数):4040 标注…...
Lua 与 C#交互
Lua 与C#交互 前提 Lua是一种嵌入式脚本语言,Lua的解释器是用C编写的,因此可以方便的与C/C进行相互调用。轻量级 Lua语言的官方版本只包括一个精简的核心和最基本的库,这使得Lua体积小、启动速度快,也适合嵌入在别的程序里。 交…...

【办公类】大组工会学习(文心一言+Python批量)
背景需求: 每学期要写一份工会的大组政治学习读后感(9月-1月,共5次) 学习内容 9月、10月、11月、12月、1月的学习内容文字稿 在班级里,我擅长电脑工作,所以这种写的工作都包了。 中2班三位老师一共写3篇&…...

项目管理工作流是什么?项目管理工作流管理实战技巧!
项目管理工作流是指在协作过程中通过限制任务状态的流转进行流程控制的一种方式。项目从启动到完成所经历的一系列有序、可控的步骤和流程,它详细描述了项目执行过程中各项任务和活动的顺序、依赖关系、责任人以及完成标准等,是项目成功执行的重要保障。…...

leveldb源码剖析(二)——LSM Tree
LSM Tree LSM Tree:Log-Structured Merge Tree,日志结构合并树。是一种频繁写性能很高的数据结构。 LSM Tree将写入操作与合并操作分离,数据首先写入磁盘中的日志文件(WAL),随后写入内存缓存,…...
三十六、Gin注册功能-检查账号是否存在
一、初始化 1、在cms.go中添加数据库连接方法 func connDB(app *CmsApp) {mysqlDB, err : gorm.Open(mysql.Open("root:rootroottcp(localhost:3306)/?charsetutf8mb4&parseTimeTrue&locLocal"))if err ! nil {panic(err)}db, err : mysqlDB.DB()if err !…...

什么是期权对冲?
今天期权懂带你了解什么是期权对冲?期权对冲的选择取决于投资者的市场预期和风险承受能力,通过合理使用期权对冲策略,可以有效减少风险并优化投资组合的表现。 期权对冲是什么? 期权是一种支持双向交易的投资产品,期…...
什么是数据库课程设计?
文章目录 前言一、课程设计目的二、课程设计流程三、设计要点四、示例项目总结 前言 数据库课程设计是一个综合性的实践过程,旨在通过实际项目的设计与实现,加深学生对数据库理论知识的理解和应用能力。 以下是一个关于数据库课程设计的基本框架和要点&…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...