按顺序切面,而不是随机

问题描述 投票:0回答:1

我创建了一个可以识别和裁剪人脸的 Python 代码。但问题是它随机裁剪面部,而不是按照包含所有面部的原始图像中的顺序。 请注意:代码从上到右按顺序裁剪面部,直到到达最后一个面部。

请将代码放在名为 (输入图像) 的文件夹中,其中包含包含收集的人脸的图像。 并创建一个名为 Output Images 的文件夹来存储裁剪后的脸部。 使用人脸识别xml文件 haarcascade_frontalface_default.xml text

代码:

import os
import cv2
import numpy as np
import os, os.path
# Load the cascade classifier
#download this here https://raw.githubusercontent.com/opencv/opencv/4.x/data/haarcascades/haarcascade_frontalface_default.xml just go there and ctrl + s
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")


#rename a file 
#for dirname in os.listdir("."):
#    if os.path.isdir(dirname):
#        for i, filename in enumerate(os.listdir(dirname)):
#            os.rename(dirname + "/" + filename, dirname + "/" + str(i) + ".jpg")

# Read the input image
img = cv2.imread("Input Images/image.jpg")
#let's double the size of our image
img_double=cv2.resize(img,None,fx=1,fy=1,interpolation=cv2.INTER_CUBIC)
# let's do the resizing by exact dimensions
image_resize=cv2.resize(img,(600,700),interpolation=cv2.INTER_AREA)


# Convert into grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Detect faces
faces = face_cascade.detectMultiScale( gray, 
    scaleFactor=1.1, 
    minNeighbors=5, 
    minSize=(150, 150), )


# loop over all detected faces
if len(faces) > 0:
   for i, (x,y,w,h) in enumerate(faces):
       
      
      #face = img[y:y+h, x:x+w]
      face = img[y-65:y+h+40,x-40:x+w+55]
   
  
    # cv2.imshow(f"Cropped Face {i}", face)

      cv2.imwrite("Output Images/" f'0{i}.jpg', face)
      print(f"0{i}.jpg is saved")

  
# concatenate image Vertically 
#Verti = np.concatenate((img, img), axis=0) 

# Number of all detected faces      
print("[INFO] Found {0} Faces.".format(len(faces)))


# display the image with detected faces
cv2.imshow('scaling_exact',image_resize)
cv2.waitKey(0)
cv2.destroyAllWindows()

原图 示例

请要求:代码从上到右按顺序裁剪面部,直到到达最后一个面部。 示例

[原图] (https://i.sstatic.net/mdTMAMpD.jpg)

python python-3.x opencv computer-vision
1个回答
0
投票

这是一个排序任务。

假设您已找到所有面部框,现在计算每个框的中心。我们将与这些中心点合作。

您会假设这些点形成一个网格。

您不知道行数,因此您必须计算。

为此,我们将 Y 坐标聚类为 k=1..N 个簇,对于最小的 k,使得所有簇都具有“低”方差。如果一个簇必须保存多于一行,则其方差将明显大于保存单行的簇。

对于该阈值,我将在此处使用

200
,因为行之间的距离比该阈值更远,并且每行中 Y 的变化远低于该阈值。

import numpy as np
from sklearn.cluster import KMeans
# some points I picked out of your picture
boxes = np.array([
    [  90,  166,  180,  312],
    [ 485,  205,  148,  258],
    [ 853,  183,  182,  288],
    [1229,  220,  186,  294],
    [1647,  222,  158,  256],
    [2024,  178,  132,  250],
    [  71,  894,  162,  280],
    [ 460,  867,  166,  302],
    [ 849,  921,  174,  336],
    [1254,  918,  180,  318],
    [1612,  932,  204,  304],
    [2009,  905,  188,  302],
    [  86, 1643,  152,  298],
    [ 435, 1600,  210,  284],
    [ 825, 1569,  208,  336],
    [1256, 1616,  170,  304],
    [1605, 1586,  182,  284],
    [2008, 1606,  190,  292],
    [  71, 2310,  160,  284],
    [ 448, 2313,  214,  274],
    [ 836, 2387,  168,  278],
    [1237, 2362,  172,  298],
    [1624, 2346,  180,  260],
    [2020, 2327,  174,  232]])

points = boxes[:, 0:2] + boxes[:, 2:4] / 2
np.random.shuffle(points)
def find_least_k(values, threshold):
    for k in range(1, len(values) + 1):
        kmeans = KMeans(n_clusters=k, random_state=0).fit(values.reshape(-1, 1))
        centers = kmeans.cluster_centers_.flatten()
        labels = kmeans.labels_
        stddevs = np.array([values[labels == i].std() for i in range(k)])

        if stddevs.max() < threshold:
            return k, centers, labels

Y_values = points[:, 1]
best_k, centers, labels = find_least_k(Y_values, threshold=200)

# sorting the rows
permutation = np.argsort(centers)
invperm = np.argsort(permutation)

centers = centers[permutation]
labels = invperm[labels]

points_by_row = [
    points[labels == i]
    for i in range(best_k)
]

points_sorted = np.array([
    row[np.argsort(row[:, 0])]
    for row in points_by_row
])

输入、输出:

input output

© www.soinside.com 2019 - 2024. All rights reserved.