【问题标题】:Drawing fancy rectangle around face在脸部周围绘制精美的矩形
【发布时间】:2018-02-12 15:47:21
【问题描述】:

我正在使用以下代码检测人脸并在人脸顶部绘制矩形。

while True:
    # get video frame
    ret, img = cap.read()

    input_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img_h, img_w, _ = np.shape(input_img)

    detected = detector(input_img, 1)

    for i, d in enumerate(detected):
        x1, y1, x2, y2, w, h = d.left(), d.top(), d.right() + 1, d.bottom() + 1, d.width(), d.height()
        cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)

    cv2.imshow("result", img)
    key = cv2.waitKey(30)

    if key == 27:
        break

矩形看起来是这样的:

但是我试图得到一个类似于这样的矩形:

有什么 OpenCV 或 dlib 函数可以帮助我得到这种有效的矩形吗?

【问题讨论】:

  • 有多种绘图功能可让您绘制linesarcs。似乎是实现您想要的一切所需的一切。
  • 糟糕,找不到页面。
  • @DheerajMPai 不错。我设法找到了图像(幸运的是路径只是稍微改变了)并在本地上传了它们,所以将来应该会很好。谢谢(感谢赏金:))

标签: python opencv image-processing dlib


【解决方案1】:

你可以使用绘制linesarcs的函数来实现你想要的。

您要绘制的框架由 4 个相似的部分(每个角一个)组成,每个部分都旋转(或镜像)。

让我们看看左上角:

如您所见,我们需要绘制 2 条线段(长度为 d)和圆弧(半径为四分之一圆 r)。

假设左上角的坐标是(x1, y1)

这意味着圆弧的中心点在(x1 + r, y1 + r)

其中一行将从(x1 + r, y1) 变为(x1 + r + d, y1)

另一行将从(x1, y1 + r) 转到(x1, y1 + r + d)

其他角落也会发生类似的情况。


示例代码:

import cv2
import numpy as np

# ============================================================================

def draw_border(img, pt1, pt2, color, thickness, r, d):
    x1,y1 = pt1
    x2,y2 = pt2

    # Top left
    cv2.line(img, (x1 + r, y1), (x1 + r + d, y1), color, thickness)
    cv2.line(img, (x1, y1 + r), (x1, y1 + r + d), color, thickness)
    cv2.ellipse(img, (x1 + r, y1 + r), (r, r), 180, 0, 90, color, thickness)

    # Top right
    cv2.line(img, (x2 - r, y1), (x2 - r - d, y1), color, thickness)
    cv2.line(img, (x2, y1 + r), (x2, y1 + r + d), color, thickness)
    cv2.ellipse(img, (x2 - r, y1 + r), (r, r), 270, 0, 90, color, thickness)

    # Bottom left
    cv2.line(img, (x1 + r, y2), (x1 + r + d, y2), color, thickness)
    cv2.line(img, (x1, y2 - r), (x1, y2 - r - d), color, thickness)
    cv2.ellipse(img, (x1 + r, y2 - r), (r, r), 90, 0, 90, color, thickness)

    # Bottom right
    cv2.line(img, (x2 - r, y2), (x2 - r - d, y2), color, thickness)
    cv2.line(img, (x2, y2 - r), (x2, y2 - r - d), color, thickness)
    cv2.ellipse(img, (x2 - r, y2 - r), (r, r), 0, 0, 90, color, thickness)

# ============================================================================

img = np.zeros((256,256,3), dtype=np.uint8)

draw_border(img, (10,10), (100, 100), (127,255,255), 1, 10, 20)
draw_border(img, (128,128), (240, 160), (255,255,127), 1, 5, 5)

cv2.imwrite('round_rect.png', img)

结果:

【讨论】:

  • 你是个超级天才!
  • 太棒了!!这真的很有帮助!我太板了,看不起愚蠢的绿色矩形输出
  • 如果我有更多的代表。我会把他们全部作为赏金给予的
【解决方案2】:

我做了一些天真的事情。您可以使用函数进行进一步修改。

步骤:

  1. 我在文本周围手动标记了一个矩形并提取了 4 个点。

  2. 然后我固定了从这 4 个点绘制的线的长度。

结果:

使用的功能:

  • cv2.line()
  • cv2.rectangle()

请参阅THIS LINK 了解它们的使用详情。

【讨论】:

  • 您上面的答案非常棒。也许你可以编辑
  • 不,可能是您添加了整个代码。而不是仅仅添加链接
【解决方案3】:

与其寻找可让您制作精美矩形的函数/库,不如采用以下策略:

第 1 步 - 下载您想要的矩形图像,使其只包含角落的 4 个笔划,其余的背景应为黑色强>。

第 2 步 - 在您的代码中,使用 imread 将此图像保存为 Mat 对象:

border = cv2.imread('your_img.jpg')

第 3 步 - 修改您的for 循环以在检测到的矩形上叠加border Mat,如下所示:

for i, d in enumerate(detected):
    x1, y1, x2, y2, w, h = d.left(), d.top(), d.right() + 1, d.bottom() + 1, d.width(), d.height()

    #cv2.rectangle won't be needed anymore
    #cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)

    roi=img[y1+h/2-100:y1+h/2+100,x1+w/2-100:x1+w/2+100]
    #this points to a section in original image
    cv2.addWeighted(roi,1,border,1,0,roi)

确保roiborder的大小相同,否则你的代码会崩溃。

这将在您的输入帧上叠加边角笔划,并忽略黑色背景。

【讨论】:

    【解决方案4】:

    感谢@Dan Mašek 的建议。您可以通过这种方式轻松绘制精美的矩形。您可以在这里查看完整的详细信息:Drawing Fancy Round Rectangle around the Face

    def draw_border(img, pt1, pt2, color, thickness, r, d):
        x1,y1 = pt1
        x2,y2 = pt2
    
        # Top left
        cv2.line(img, (x1 + r, y1), (x1 + r + d, y1), color, thickness)
        cv2.line(img, (x1, y1 + r), (x1, y1 + r + d), color, thickness)
        cv2.ellipse(img, (x1 + r, y1 + r), (r, r), 180, 0, 90, color, thickness)
    
        # Top right
        cv2.line(img, (x2 - r, y1), (x2 - r - d, y1), color, thickness)
        cv2.line(img, (x2, y1 + r), (x2, y1 + r + d), color, thickness)
        cv2.ellipse(img, (x2 - r, y1 + r), (r, r), 270, 0, 90, color, thickness)
    
        # Bottom left
        cv2.line(img, (x1 + r, y2), (x1 + r + d, y2), color, thickness)
        cv2.line(img, (x1, y2 - r), (x1, y2 - r - d), color, thickness)
        cv2.ellipse(img, (x1 + r, y2 - r), (r, r), 90, 0, 90, color, thickness)
    
        # Bottom right
        cv2.line(img, (x2 - r, y2), (x2 - r - d, y2), color, thickness)
        cv2.line(img, (x2, y2 - r), (x2, y2 - r - d), color, thickness)
        cv2.ellipse(img, (x2 - r, y2 - r), (r, r), 0, 0, 90, color, thickness)
    
    
    def detect(path,img):
        cascade = cv2.CascadeClassifier(path)
    
        img=cv2.imread(img,1)
        # converting to gray image for faster video processing
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
        rects = cascade.detectMultiScale(gray, 1.2, 3,minSize=(50, 50))
        # if at least 1 face detected
        if len(rects) >= 0:
            # Draw a rectangle around the faces
            for (x, y, w, h) in rects:
                draw_border(img, (x, y), (x + w, y + h), (255, 0, 105),4, 15, 10)
            # Display the resulting frame
            cv2.imshow('Face Detection', img)
            # wait for 'c' to close the application
            cv2.waitKey(0)
    

    【讨论】:

    • 你刚刚复制粘贴了第一个答案老兄,无论如何谢谢
    • 这就是为什么我也感谢他的代码。我认为您没有正确阅读我的评论。检查正确,我尝试用人脸检测和花式矩形来回答问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    • 1970-01-01
    • 2022-01-09
    • 2021-12-17
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多