【问题标题】:How to expand 2d array (30x20) to 36x60, which is contained in 620x480 2d array?如何将二维数组(30x20)扩展到 36x60,包含在 620x480 二维数组中?
【发布时间】:2019-10-09 00:36:57
【问题描述】:

起始数据:二维数组 (620x480) 包含图像,其中显示人脸,二维数组 (30x20) 包含眼睛图像。人脸图像包括眼睛图像。

如何将眼睛图像扩展到 36x60 以包含面部图像的像素?有现成的解决方案吗?

另一个类似的任务:眼睛图像的大小为 37x27。如何将眼睛图像扩展到目标(最接近 36x60)尺寸,例如39x65,即在调整大小之前保持所需的纵横比,然后调整为 36x60。

测试代码(项目由reference提供):

import dlib
import cv2 as cv
from imutils.face_utils import shape_to_np
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('res/model.dat')


frame = cv.imread('photo.jpg')
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

img = frame.copy()
dets = detector(gray, 0)

for i, det in enumerate(dets):
    shape = shape_to_np(predictor(gray, det))
    shape_left_eye = shape[36:42]

    x, y, h, w = cv.boundingRect(shape_left_eye)
    cv.rectangle(img, (x, y), (x + h, y + w), (0, 255, 0), 1)
    cv.imwrite('file.png', frame[y: y+w, x: x+h])

图像 42x13:

【问题讨论】:

标签: arrays python-3.x numpy opencv


【解决方案1】:

第一部分你可以用cv2.matchTemplate在脸上找到眼睛区域,然后根据你想要的大小放大。你可以阅读更多关于它的信息here

使用的人脸图像

使用的眼睛图像

我的眼睛大小 (12, 32)。

face = cv2.imread('face.jpg', 0)
eye = cv2.imread('eye.jpg', 0)
w, h = eye.shape[::-1]
res = cv2.matchTemplate(face,eye,cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(face ,top_left, bottom_right, 255, 2)
cv2.imshow('image', face)
cv2.waitKey(0)
cv2.destroyAllWindows()

这段代码的结果是:

现在我有眼睛的左上角和右下角坐标,在 top_left = (112, 108) 和 bottom_right = (144, 120) 处匹配。现在要将它们扩展为 36x60 的尺寸,我只需从 top_left 中减去所需的值,然后在 bottom_right 中添加所需的值。

编辑 1

该问题已被编辑,表明已将 dlib 与经过训练以执行左眼检测的模型一起使用。使用我获得的相同代码

按照上面的建议,我找到了top_left = (x,y)bottom_right = (x+w, y+h)

现在,如果眼睛尺寸小于 36x60,那么我们只需将其周围的区域扩展为 36x60,否则我们必须将其扩展为不影响纵横比,然后调整其大小并且不能硬编码.使用的完整代码是:

import dlib
from imutils.face_utils import shape_to_np
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('res/model.dat')

face = cv2.imread('face.jpg', 0)
img = face.copy()
dets = detector(img, 0)
for i, det in enumerate(dets):
    shape = shape_to_np(predictor(img, det))
    shape_left_eye = shape[36:42]
    x, y, w, h = cv2.boundingRect(shape_left_eye)
    cv2.rectangle(face, (x, y), (x + w, y + h), (255, 255, 255), 1)
top_left = (x, y)
bottom_right = (x + w, y + h)
if w <= 36 and h <= 60:
    x = int((36 - w)/2)
    y = int((60 - h)/2) 
else:
    x1 = w - 36
    y1 = h - 60
    if x1 > y1:
        x = int((w % 3)/2)
        req = (w+x) * 5 / 3
        y = int((req - h)/2)
    else:
        y = int((h % 5)/2)
        req = (y+h) * 3 / 5
        x = int((req - w)/2)
top_left = (top_left[0] - x, top_left[1] - y)
bottom_right = (bottom_right[0] + x, bottom_right[1] + y)        
extracted = face[top_left[1]:bottom_right[1], top_left[0]:bottom_right[0]]
result = cv2.resize(extracted, (36, 60),  interpolation = cv2.INTER_LINEAR)
cv2.imshow('image', face)
cv2.imshow('imag', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

这为我们提供了 36x60 的眼睛区域:

这可以解决眼睛尺寸小于 36x60 的情况。对于第二种情况,当眼睛的大小大于 36x60 区域时,我使用了face = cv2.resize(face, None, fx=4, fy=4, interpolation = cv2.INTER_CUBIC)。结果是:

检测到的眼睛大小为 (95, 33),提取的区域为 (97, 159),非常接近调整大小之前的 3:5 纵横比,这也满足了第二个任务。

【讨论】:

  • 我刚刚看到您的编辑。您是否希望我在答案中编辑或使用 dlib 解决问题?
  • 我需要这个来处理视频流。扩展参数能够动态计算。在每一帧中眼睛的不同坐标。另外,如果我有超出边界的眼睛大小,我必须计算大于 36x60 的大小,然后将大小调整为 36x60。
  • 眼睛大小可以随时大于36x60吗?
  • 有时是的。例如 37x27,在这种情况下需要扩展到与 36x60 相关的最接近的尺寸(在这种特定情况下为 39x65,将 3/5 添加到 36x60)
  • 现在好吗? @millka_15
猜你喜欢
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 2015-07-21
  • 2011-02-03
  • 2021-11-26
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多