在脸周围画出花哨的矩形
Drawing fancy rectangle around face
我正在使用以下代码检测面部并在面部上方绘制矩形。
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 函数可以帮助我获得这种有效的矩形?
与其寻找一个 function/lib 让您制作花哨的矩形,以下策略可能更容易:
第 1 步 - 下载所需矩形的图像,使其仅包含角的 4 个笔划,和其余部分背景应该是黑色.
步骤 2 - 在您的代码中,使用 imread
将此图像保存为 Mat 对象:
border = cv2.imread('your_img.jpg')
步骤 3 - 修改您的 for
循环以 将 border
垫子叠加在检测到的矩形上 ,如下图:
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)
确保 roi
和 border
的大小相同,否则您的代码会崩溃。
这会将边角笔划叠加到您的输入框上,并忽略黑色背景。
我做了一些幼稚的事情。您可以使用函数进一步修改来实现。
步骤:
我在文本周围手动标记了一个矩形并提取了 4 个点。
然后我给这4个点定了一条线的长度
结果:
使用的函数:
cv2.line()
cv2.rectangle()
有关它们的用法的详细信息,请参阅 THIS LINK。
你可以通过绘制函数来实现你想要的lines and arcs。
您要绘制的框架由 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)
结果:
感谢@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)
我正在使用以下代码检测面部并在面部上方绘制矩形。
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 函数可以帮助我获得这种有效的矩形?
与其寻找一个 function/lib 让您制作花哨的矩形,以下策略可能更容易:
第 1 步 - 下载所需矩形的图像,使其仅包含角的 4 个笔划,和其余部分背景应该是黑色.
步骤 2 - 在您的代码中,使用 imread
将此图像保存为 Mat 对象:
border = cv2.imread('your_img.jpg')
步骤 3 - 修改您的 for
循环以 将 border
垫子叠加在检测到的矩形上 ,如下图:
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)
确保 roi
和 border
的大小相同,否则您的代码会崩溃。
这会将边角笔划叠加到您的输入框上,并忽略黑色背景。
我做了一些幼稚的事情。您可以使用函数进一步修改来实现。
步骤:
我在文本周围手动标记了一个矩形并提取了 4 个点。
然后我给这4个点定了一条线的长度
结果:
使用的函数:
cv2.line()
cv2.rectangle()
有关它们的用法的详细信息,请参阅 THIS LINK。
你可以通过绘制函数来实现你想要的lines and arcs。
您要绘制的框架由 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)
结果:
感谢@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)