如何标记 OpenCV 中两个数组中都存在的特征?

How to mark features which are present in both arrays in OpenCV?

我正在尝试编写一个 Python 3.7 脚本来使用 OpenCV Haar 分类器文件检测面部和特征,该文件将图像存储为 n 维 Numpy 数组。现在我只使用两个功能: - 整个脸 - 眼睛 这两个都是使用两个不同的分类器获得的。 该代码检测图像中是否存在这两种特征,然后使用每个特征的 for 循环内的 cv2.rectangle() 函数用矩形标记它们,即一个用于检测到的面部,一个用于检测到的眼睛。

我希望脚本仅在面部阵列和眼睛阵列中找到这些点时才标记眼睛矩形。 numpy.intersect1d() 仅查找一维数组中的交集。

我什至试过了

for x,y,w,h in eyes and x,y,w,h in faces:

它所做的只是return这条错误信息:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

如有任何帮助,我们将不胜感激。

正在Windows10 64位上尝试,代码是Pycharm2019年写的,OpenCV导入为CV2。

# Creating the cascade classifier objects.
face_cascade = 
cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")

# Entering and displaying the original image.
img = cv2.imread("filename.jpg", 1)
cv2.imshow("Original Images",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Convert the image to Black and White and store in a variable.
gry_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

faces = face_cascade.detectMultiScale(gry_img, scaleFactor = 1.05, minNeighbors = 8)
eyes = eye_cascade.detectMultiScale(gry_img, scaleFactor = 1.30, minNeighbors = 12)

# Now, we mark the detected features with a rectangle on the original image.
for x,y,w,h in faces:
    img = cv2.rectangle(img, (x,y), (x+w, y+h), (255, 21, 21), 3) # Blue.


for x,y,w,h in eyes:
    img = cv2.rectangle(img, (x,y), (x+w, y+h), (255, 255, 24), 3) # Cyan.

cv2.imshow("Detected Faces and Eyes",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

只有在面部​​特征数组中也找到了眼睛特征时,我才需要标记它们。

OpenCV docs 中已经提出了解决此问题的更好方法。它建议不要通过整个图像来检测眼睛,而应该先检测面部,然后裁剪图像,并将裁剪后的图像用于眼睛检测。要裁剪面部图像,您可以使用 numpy 切片作为:

for x,y,w,h in faces:
    face_img = gry_img[y:y+h, x:x+w]
    # Now detect the eyes in this `face_img` only.
    eyes = eye_cascade.detectMultiScale(face_img, scaleFactor = 1.30, minNeighbors = 12)

天哪,我现在是不是觉得自己很蠢。好吧:

正如 ZdaR 所说,OpenCV 文档确实给出了一个完美的示例,说明如何实现我需要的结果,其要点是:

for x,y,w,h in faces:
    face_img = gry_img[y:y+h, x:x+w]
    # Now detect the eyes in this `face_img` only.
    eyes = eye_cascade.detectMultiScale(face_img, scaleFactor = 1.30, minNeighbors = 12)

除此之外我还需要做的,显然是将原始图像裁剪到面部坐标,以便 eye-features 被绘制。我仍然不确定 是否应该 工作,但现在看来添加额外的行 确实 工作。

最终有效的代码:

faces = face_cascade.detectMultiScale(gry_img, scaleFactor = 1.05, minNeighbors = 10)
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y),(x + w, y + h), (255, 0, 0), 3)
    gry_eye = gry_img[y:y+h, x:x+w]
    eye_img = img[y:y + h, x:x + w]
    eyes = eye_cascade.detectMultiScale(gry_eye, scaleFactor = 1.05, minNeighbors = 5)
    for (x, y, w, h) in eyes:
        cv2.rectangle(eye_img, (x, y), (x + w, y + h), (255, 255, 24), 3)

好吧,这是一次学习经历。 感谢 ZdaR 的帮助!