检测视频中穿红色衣服的人

Detect person wearing red in a video

我正在和很多人一起制作视频,其中很少有人穿着红色 T 恤。我用人员检测和跟踪模型检测和跟踪了所有人。如何区分穿红色衣服的人和其他人。

我正在读取 OpenCV 格式的帧。如果我知道坐标,假设 x,y 是颜色为红色的物体的坐标。如何从OpenCV格式的坐标中获取颜色信息并检查是否在红色范围内?

我只需要高亮别人穿红衣服的人的边界框。

谁能帮我找出解决办法。 谢谢!

将颜色 space 更改为 HSV 并找到颜色的 Hue 值范围的更好方法。

  • 拍摄视频的每一帧
  • 先检测人物再提取人物区域(source)
  • 从 BGR 转换为 HSV color-space
  • 对红色范围的 HSV 图像设置阈值

识别红色 t-shirt 视频中的人

我们可以使用以下代码识别图像中的人体区域

import time

import cv2
import imutils
import numpy as np
from imutils.video import FPS
# import the necessary packages
from imutils.video import VideoStream


def get_centered_contours(mask):
  # find contours
  cntrs = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
  sorted_contours = sorted(cntrs, key=cv2.contourArea, reverse=True)
  filterd_contours = []
  if sorted_contours != []:
    for k in range(len(sorted_contours)):
      if cv2.contourArea(sorted_contours[k]) < 1000.0:
        filterd_contours = sorted_contours[0:k]
        return filterd_contours
  return filterd_contours


def check_red_colour_person(roi):
  hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
  # define range of blue color in HSV
  lower_red = np.array([0, 50, 50])
  upper_red = np.array([10, 255, 255])
  # Threshold the HSV image to get only blue colors
  mask = cv2.inRange(hsv, lower_red, upper_red)
  cnts = get_centered_contours(mask)
  if cnts != []:
    return True
  else:
    return False


# construct the argument parse and parse the arguments
prototxt = 'MobileNetSSD_deploy.prototxt.txt'
model = 'MobileNetSSD_deploy.caffemodel'
confidence_level = 0.8

# initialize the list of class labels MobileNet SSD was trained to
# detect, then generate a set of bounding box colors for each class
CLASSES = ["person"]
COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3))

# load our serialized model from disk
print("[INFO] loading model...")
net = cv2.dnn.readNetFromCaffe(prototxt, model)

# initialize the video stream, allow the cammera sensor to warmup,
# and initialize the FPS counter
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)
fps = FPS().start()

# loop over the frames from the video stream
while True:
  try:
    # grab the frame from the threaded video stream and resize it
    # to have a maximum width of 400 pixels
    frame = vs.read()
    frame = imutils.resize(frame, width=400)

    # grab the frame dimensions and convert it to a blob
    (h, w) = frame.shape[:2]
    blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)),
                                 0.007843, (300, 300), 127.5)

    # pass the blob through the network and obtain the detections and
    # predictions
    net.setInput(blob)
    detections = net.forward()

    # loop over the detections
    for i in np.arange(0, detections.shape[2]):
      # extract the confidence (i.e., probability) associated with
      # the prediction
      confidence = detections[0, 0, i, 2]

      # filter out weak detections by ensuring the `confidence` is
      # greater than the minimum confidence
      if confidence > confidence_level:
        # extract the index of the class label from the
        # `detections`, then compute the (x, y)-coordinates of
        # the bounding box for the object
        idx = int(detections[0, 0, i, 1])
        box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
        (startX, startY, endX, endY) = box.astype("int")

        roi = frame[startY:endY, startX:endX]
        # cv2.imwrite('roi_{}_{}_{}_{}.png'.format(startX,startY,endX,endY),roi)
        if check_red_colour_person(roi):
          label = "{}: {:.2f}%".format(' Red T-shirt person',
                                       confidence * 100)
          cv2.imwrite(
              'Red-T-shirt_guy_{}_{}_{}_{}.png'.format(startX, startY, endX,
                                                       endY), roi)

          cv2.rectangle(frame, (startX, startY), (endX, endY),
                        (0, 0, 255), 2)
        else:
          cv2.rectangle(frame, (startX, startY), (endX, endY),
                        (255, 0, 0), 2)
      y = startY - 15 if startY - 15 > 15 else startY + 15
      cv2.putText(frame, label, (startX, y),
                  cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2)

      cv2.imshow("Frame", frame)
      key = cv2.waitKey(1) & 0xFF

      # if the `q` key was pressed, break from the loop
      if key == ord("q"):
        break

      # update the FPS counter
      fps.update()
  except Exception as e:
    print("Exception is occured")
    continue
# stop the timer and display FPS information
fps.stop()
print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))

# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()

您可以设置颜色边界

boundaries = [
([17, 15, 100], [50, 56, 200])]

所以这里是元组 ([17, 15, 100], [50, 56, 200]) .

在这里,我们是说图像中所有具有 R >= 100、B >= 15 和 G >= 17 以及 R <= 200、B <= 56 和 G <= 的像素50 将被视为红色。

你可以像下面这样实现:

for (lower, upper) in boundaries:
    lower = np.array(lower, dtype = "uint8")
    upper = np.array(upper, dtype = "uint8")
    # find the colors within the specified boundaries and apply
    # the mask
    mask = cv2.inRange(image, lower, upper)
    output = cv2.bitwise_and(image, image, mask = mask)
    # show the images
    cv2.imshow("images", np.hstack([image, output]))