如何根据检测到的物体的位置绘制三角形箭头

时间:2021-02-20 16:28:21

标签: python opencv

我正在做一个物体检测项目。

我有我的代码。我是按照教程写的。在教程中,这家伙在 opencv 中为检测到的每个对象绘制了一个矩形。

但我想将矩形更改为三角形或箭头。

让我用代码解释===>

在我的函数中,我检测对象。 在这里我为检测到的对象绘制矩形==>

 cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)

但是我想把这个矩形改成一个三角形。(我想把三角形的位置设置到物体的上方。 就像在这些图片中一样:::

这是三角形的物体检测 [![在此处输入图片描述][1]][1]

这是我想做的东西而不是矩形::: [![在此处输入图片描述][2]][2]

如何制作带有检测到的物体位置的三角形/箭头? 我所有的代码都在这里==>

from os.path import sep
import cv2 as cv2
import numpy as np
import json

# Camera feed
cap_cam = cv2.VideoCapture(0)

ret, frame_cam = cap_cam.read()

hey = 0

print(cv2. __version__)

whT = 320
confThreshold =0.5
nmsThreshold= 0.2

classesFile = "coco.names"
classNames = []
with open(classesFile, 'rt') as f:
    classNames = f.read().rstrip('\n').split('\n')
print(classNames)
## Model Files
modelConfiguration = "custom-yolov4-tiny-detector.cfg"
modelWeights = "custom-yolov4-tiny-detector_last.weights"
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
def findObjects(outputs,img):
    global hey
    global previousHey  
    hT, wT, cT = img.shape
    bbox = []
    classIds = []
    confs = []
    for output in outputs:
        for det in output:
            scores = det[5:]
            classId = np.argmax(scores)
            confidence = scores[classId]
            if confidence > confThreshold:
                w,h = int(det[2]*wT) , int(det[3]*hT)
                x,y = int((det[0]*wT)-w/2) , int((det[1]*hT)-h/2)
                bbox.append([x,y,w,h])
                classIds.append(classId)
                confs.append(float(confidence))
    global indicates
    indices = cv2.dnn.NMSBoxes(bbox, confs, confThreshold, nmsThreshold)
    hey = 0
    for i in indices:
        i = i[0]
        box = bbox[i]
        x, y, w, h = box[0], box[1], box[2], box[3]
        # print(x,y,w,h)
        cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
        
        #cv2.line(img, (350,400), (x, y), (255,0,0), 4)
        #cv2.line(img, (400,400), (x + 50 , y), (255,0,0), 4)
        #cv.putText(img,f'{classNames[classIds[i]].upper()} {int(confs[i]*100)}%',
                  #(x, y-10), cv.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 255), 2)
        print('success')
        hey = 1
            
        
video_frame_counter = 0
while cap_cam.isOpened():
    img = cv2.imread('photos' + sep + 'lutfen.jpg')
    #BURADA OK VİDEOSU OYNATILACAK
    #if not decetiona diye dene yarın.
    blob = cv2.dnn.blobFromImage(img, 1 / 255, (whT, whT), [0, 0, 0], 1, crop=False)
    net.setInput(blob)
    layersNames = net.getLayerNames()
    outputNames = [(layersNames[i[0] - 1]) for i in net.getUnconnectedOutLayers()]
    outputs = net.forward(outputNames)
    findObjects(outputs,img)
    cv2.imshow('Image', img)
    
    # Video feed
    if hey == 1:
        filename = 'photos' + sep + 'Baslksz-3.mp4'
        cap_vid = cv2.VideoCapture(filename)
        
    if hey == 0:
        filename = 'photos' + sep + 'vid2.mp4'
        cap_vid = cv2.VideoCapture(filename)    
    print(hey)
    ret, frame_vid = cap_vid.read()

#cap_cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
#cap_cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

# Resize the camera frame to the size of the video
    height = int(cap_vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
    width = int(cap_vid.get(cv2.CAP_PROP_FRAME_WIDTH))
    # Capture the next frame from camera
    ret, frame_cam = cap_cam.read()
    video_frame_counter += 1
    if video_frame_counter == cap_vid.get(cv2.CAP_PROP_FRAME_COUNT):
            video_frame_counter = 0
            cap_vid.set(cv2.CAP_PROP_POS_FRAMES, 0)
    frame_cam = cv2.resize(frame_cam, (width, height), interpolation = cv2.INTER_AREA)

    #ret = cap_vid.set(cv2.CAP_PROP_POS_MSEC, time_passed)

    ret, frame_vid = cap_vid.read()
    if not ret:
        print('Cannot read from video stream')
        break

    # Blend the two images and show the result
    tr = 0.4 # transparency between 0-1, show camera if 0
    frame = ((1-tr) * frame_cam.astype(np.float) + tr * frame_vid.astype(np.float)).astype(np.uint8)
    cv2.imshow('Transparent result', frame)
    if cv2.waitKey(1) == 27: # ESC is pressed
        break
    
cap_cam.release()
cap_vid.release()
cv2.destroyAllWindows()

1 个答案:

答案 0 :(得分:3)

简单的方法

您可以使用 cv.arrowedLine() 函数绘制与您想要的类似的东西。例如,要在矩形上方绘制一个红色箭头:

center_x = x + w//2
cv2.arrowedLine(img, (center_x, y-50), (center_x, y-5), (0,0,255), 2, 8, 0, 0.5)

这应该给出类似于下图的结果。查看OpenCV documentation中函数参数的说明。您可以更改其大小、厚度、颜色等。

box with arrow

自定义箭头形状

如果您想更好地控制箭头的形状,您可以定义一个轮廓(逐个顶点)并使用 cv.drawContours() 来渲染它。例如:

# define the arrow shape
shape = np.array([[[0,0],[-25,-25],[-10,-25],[-10,-50],
                   [10,-50],[10,-25],[25,-25]]])

# move it to the desired position
cx = x + w // 2
cy = y - 5
shape[:,:,0] += cx
shape[:,:,1] += cy

# draw it
cv2.drawContours(img, shape, -1, (0, 255, 0), -1)

此代码段将为您提供下图。您可以通过更改 shape 数组中的顶点来调整形状,或者查看 documentation 以更改 OpenCV 绘制它的方式。

enter image description here

相关问题