1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 07:13:02 +04:00
Files
Abhishek Gola 2ec6a6bb65 Merge pull request #28588 from abhishek-gola:ORT_GPU_wrapper
Added OnnxRuntime GPU wrapper #28588

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
2026-04-06 15:40:58 +03:00

159 lines
5.9 KiB
Python

'''
Mask R-CNN
This is an example of using Mask R-CNN for object detection and instance segmentation.
NOTE regarding OpenCV 5.0+:
The default model configuration (.pbtxt) used in this sample relies on retrieving
intermediate layers (e.g., 'detection_out_final'). OpenCV 5.0 introduces stricter
graph optimization which may prune intermediate layers not explicitly registered as outputs.
If you encounter an error such as "the number of requested and actual outputs must be the same",
please note that the provided .pbtxt may need to be updated to explicitly declare
'detection_out_final' as an output node.
'''
import cv2 as cv
import argparse
import numpy as np
parser = argparse.ArgumentParser(description=
'Use this script to run Mask-RCNN object detection and semantic '
'segmentation network from TensorFlow Object Detection API.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.')
parser.add_argument('--model', required=True, help='Path to a .pb file with weights.')
parser.add_argument('--config', required=True, help='Path to a .pxtxt file contains network configuration.')
parser.add_argument('--classes', help='Optional path to a text file with names of classes.')
parser.add_argument('--colors', help='Optional path to a text file with colors for an every class. '
'An every color is represented with three values from 0 to 255 in BGR channels order.')
parser.add_argument('--width', type=int, default=800,
help='Preprocess input image by resizing to a specific width.')
parser.add_argument('--height', type=int, default=800,
help='Preprocess input image by resizing to a specific height.')
parser.add_argument('--thr', type=float, default=0.5, help='Confidence threshold')
args = parser.parse_args()
np.random.seed(324)
# Load names of classes
classes = None
if args.classes:
with open(args.classes, 'rt') as f:
classes = f.read().rstrip('\n').split('\n')
# Load colors
colors = None
if args.colors:
with open(args.colors, 'rt') as f:
colors = [np.array(color.split(' '), np.uint8) for color in f.read().rstrip('\n').split('\n')]
legend = None
def showLegend(classes):
global legend
if not classes is None and legend is None:
blockHeight = 30
assert(len(classes) == len(colors))
legend = np.zeros((blockHeight * len(colors), 200, 3), np.uint8)
for i in range(len(classes)):
block = legend[i * blockHeight:(i + 1) * blockHeight]
block[:,:] = colors[i]
cv.putText(block, classes[i], (0, blockHeight//2), cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
cv.namedWindow('Legend', cv.WINDOW_NORMAL)
cv.imshow('Legend', legend)
classes = None
def drawBox(frame, classId, conf, left, top, right, bottom):
# Draw a bounding box.
cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0))
label = '%.2f' % conf
# Print a label of class.
if classes:
assert(classId < len(classes))
label = '%s: %s' % (classes[classId], label)
labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
top = max(top, labelSize[1])
cv.rectangle(frame, (left, top - labelSize[1]), (left + labelSize[0], top + baseLine), (255, 255, 255), cv.FILLED)
cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))
# Load a network
net = cv.dnn.readNet(cv.samples.findFile(args.model), cv.samples.findFile(args.config))
net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
winName = 'Mask-RCNN in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)
cap = cv.VideoCapture(cv.samples.findFileOrKeep(args.input) if args.input else 0)
legend = None
while cv.waitKey(1) < 0:
hasFrame, frame = cap.read()
if not hasFrame:
cv.waitKey()
break
frameH = frame.shape[0]
frameW = frame.shape[1]
# Create a 4D blob from a frame.
blob = cv.dnn.blobFromImage(frame, size=(args.width, args.height), swapRB=True, crop=False)
# Run a model
net.setInput(blob)
# NOTE: In OpenCV 5.0, requesting 'detection_out_final' will fail if the .pbtxt
# does not register it as an output. See file header for details.
t0 = cv.getTickCount()
boxes, masks = net.forward(['detection_out_final', 'detection_masks'])
t = (cv.getTickCount() - t0) / cv.getTickFrequency()
numClasses = masks.shape[1]
numDetections = boxes.shape[2]
# Draw segmentation
if not colors:
# Generate colors
colors = [np.array([0, 0, 0], np.uint8)]
for i in range(1, numClasses + 1):
colors.append((colors[i - 1] + np.random.randint(0, 256, [3], np.uint8)) / 2)
del colors[0]
boxesToDraw = []
for i in range(numDetections):
box = boxes[0, 0, i]
mask = masks[i]
score = box[2]
if score > args.thr:
classId = int(box[1])
left = 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))
boxesToDraw.append([frame, classId, score, left, top, right, bottom])
classMask = mask[classId]
classMask = cv.resize(classMask, (right - left + 1, bottom - top + 1))
mask = (classMask > 0.5)
roi = frame[top:bottom+1, left:right+1][mask]
frame[top:bottom+1, left:right+1][mask] = (0.7 * colors[classId] + 0.3 * roi).astype(np.uint8)
for box in boxesToDraw:
drawBox(*box)
# Put efficiency information.
label = 'Inference time: %.2f ms' % (t * 1000.0)
cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
showLegend(classes)
cv.imshow(winName, frame)