没有ML的实时对象检测绘图框

Drawing bbox for realtime object detection without ML

我正在尝试在没有任何 ML 的情况下进行实时对象检测。该方法是根据其颜色配置文件来识别对象。我正在尝试识别具有单一颜色的矩形对象并绘制边界框。这是代码:

import cv2
import numpy as np

class ColourBounds:
    def __init__(self, rgb):
        hsv = cv2.cvtColor(np.uint8([[[rgb[2], rgb[1], rgb[0]]]]), cv2.COLOR_BGR2HSV).flatten()

        lower = [hsv[0] - 10]
        upper = [hsv[0] + 10]

        if lower[0] < 0:
            lower.append(179 + lower[0]) # + negative = - abs
            upper.append(179)
            lower[0] = 0
        elif upper[0] > 179:
            lower.append(0)
            upper.append(upper[0] - 179)
            upper[0] = 179

        self.lower = [np.array([h, 100, 100]) for h in lower]
        self.upper = [np.array([h, 255, 255]) for h in upper]

def contains_vertical(r1, r2):
    x1, y1, w1, h1 = r1
    x2, y2, w2, h2 = r2

    return x1 <= x2 < x1 + w1 and x1 <= x2 + w2 < x1 + w1

def drawLabel(w, h, x, y, text, frame):
    cv2.rectangle(frame,(x,y),(x+w,y+h),(120,0,0),2)
    cv2.putText(frame, text, (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,255), 2)

colourMap = {"Antigen Device": ColourBounds((237,237,237))}

while(True):

    frame = cv2.imread('antigen.png')

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    rects = {}

    for name, colour in colourMap.items():
        mask = cv2.inRange(hsv, colour.lower[0], colour.upper[0])

        if len(colour.lower) == 2:
            mask = mask | cv2.inRange(hsv, colour.lower[1], colour.upper[1])

        conts, heirarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

        if (len(conts) == 0):
            continue

        biggest = sorted(conts, key=cv2.contourArea, reverse=True)[0]
        rect = cv2.boundingRect(biggest)
        x, y, w, h = rect

        if w < 50 or h < 50:
            continue

        if name == "Antigen Device":
            if any([contains_vertical(rects[n], rect) for n in rects]):
                continue

        rects[name] = rect
        drawLabel(w, h, x, y, name, frame)

    cv2.imshow('image',frame)
    k = cv2.waitKey(0) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()
cv2.waitKey(1)

但是,我没有看到边界框或标签。下面是我的形象。不应用任何更改:

您正在尝试进行“颜色检测”,然后在其周围绘制一个边界框。

最简单的方法:

第 1 步:实施颜色检测。

我实现了以下代码来为您的图像找到正确的蒙版值。玩一下轨迹条,当您对结果满意时,按 q,将为您打印蒙版的值。

注意:除了你的目标之外,你还可以找到更多的小轮廓。

我发现这个值很管用:

h_min, h_max, s_min, s_max, v_min, v_max: 0 179 0 15 223 255

import cv2
import numpy as np

def empty():
   pass


while True:

   img = cv2.imread(Path to your image)
   imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
   h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
   h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
   s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
   s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
   v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
   v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
   lower = np.array([h_min, s_min, v_min])
   upper = np.array([h_max, s_max, v_max])
   mask = cv2.inRange(imgHSV, lower, upper)
   imgResult = cv2.bitwise_and(img, img, mask=mask)

   # for OpenCV 4
   contours, _ = cv2.findContours(mask, cv2.RETR_TREE, 
   cv2.CHAIN_APPROX_NONE) 

    # ---For OpenCV 3---
    # _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, 
    # cv2.CHAIN_APPROX_NONE) 
    # ---For OpenCV 3---

   for contour in contours:
         cv2.drawContours(img, contour, -1, (0, 255, 0), 3)

   cv2.imshow("Original", img)
   cv2.imshow("Result", imgResult)

   if cv2.waitKey(27) & 0xFF == ord('q'):
       print(h_min, h_max, s_min, s_max, v_min, v_max)
       break

第 2 步:仅在您的目标周围绘制边界框。 (2 个绘图选项)

代码与之前类似,但现在我们知道了正确的值,我们将围绕我们想要的轮廓画线。我们的目标是最大的轮廓,因此我们可以使用 contourArea() 方法来提取轮廓的大小,然后仅当轮廓足够大时才绘制“边界框”。它的实现与您的代码略有不同,但您可以根据您的逻辑对其进行调整(对等高线区域的大小进行排序并仅在最大的区域上绘制)。

例如:

import cv2
import numpy as np

while True:
    frame = cv2.imread("Whosebug2pic.jpeg")
    blurred_frame = cv2.GaussianBlur(frame, (5, 5), 0)
    hsv = cv2.cvtColor(blurred_frame, cv2.COLOR_BGR2HSV)

    lower = np.array([0, 0, 223])
    upper = np.array([179, 15, 255])
    mask = cv2.inRange(hsv, lower, upper)
    
    # for OpenCV 4
    contours, _ = cv2.findContours(mask, cv2.RETR_TREE, 
       cv2.CHAIN_APPROX_NONE) 

    # ---For OpenCV 3---
    # _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, 
    # cv2.CHAIN_APPROX_NONE) 
    # ---For OpenCV 3---

    for contour in contours:
        area = cv2.contourArea(contour)
        if area > 5000:
             # -- Draw Option 1 --
             cv2.drawContours(frame, contour, -1, (0, 255, 0), 3)

             # -- Draw Option 2--
             # rect = cv2.boundingRect(contour)
             # x, y, w, h = rect
             # cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

    cv2.imshow("Mask", mask)
    cv2.imshow("Frame", frame)

    cv2.waitKey(1)

结果(绘图选项 1):

结果(绘图选项 2):