用给定的一组点扭曲图像

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

我正在尝试执行图像扭曲,但我似乎无法应用给定一组点的变换矩阵。我试图完成的是面部变形,给定的特征点总共有 68 个特征点,我已经计算了点之间的三角测量,但我似乎无法扭曲图像。

脸部.py

import numpy as np
import cv2 as cv
import dlib
from warp import triangulate, warp

def crop_faces(image1_path, image2_path):
    cropped_faces_list = []
    for img in [image1_path, image2_path]:
        image = cv.imread(img)

        # convert to grayscale of each frames
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

        # read the haarcascade to detect the faces in an image
        face_cascade = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml')
        
        # detects faces in the input image
        faces = face_cascade.detectMultiScale(gray, 1.3, 4)
        print('Number of detected faces:', len(faces))

        # Crop and save each detected face
        cropped_faces = []
        if len(faces) > 0:
            for (x, y, w, h) in faces:
                cropped_faces.append(image[y: y + h, x:x + w])

        cropped_faces_list.append(cropped_faces)
    
    return cropped_faces_list

def generate_face_correspondeces(theImage1, theImage2):
    # Detect the points of face.
    detector = dlib.get_frontal_face_detector()
    predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

    imgList = crop_faces(theImage1, theImage2)
    list1 = []
    list2 = []
    feature_points = []
    cropped_images = []
    j = 1

    for m, img_list in enumerate(imgList):
        for img in img_list:

            if (j == 1):
                currList = list1
            else:
                currList = list2

            # Ask the detector to find the bounding boxes of each face. The 1 in the
            # second argument indicates that we should upsample the image 1 time. This
            # will make everything bigger and allow us to detect more faces.

            dets = detector(img, 1)

            try:
                if len(dets) == 0:
                    raise NoFaceFound  # type: ignore
            except NoFaceFound: # type: ignore
                print("Sorry, but I couldn't find a face in the image.")

            j = j + 1

            for k, rect in enumerate(dets):

                # Get landmarks/part for the face in rect
                shape = predictor(img, rect)
                
                for i in range(0, 68):
                    x = shape.part(i).x
                    y = shape.part(i).y
                    currList.append((x, y))
                    cv.circle(img, (x, y), 1, (0, 255, 0), 2)
            
            feature_points.append(currList)
            cropped_images.append(img)

            cv.imwrite(f"test_{m}.png", img)


    return feature_points, cropped_images


img1 = './Images/mulher1.jpg'
img2 = './Images/homem.jpg'

feature_points, cropped_images = generate_face_correspondeces(img1, img2)

for i, image in enumerate(cropped_images):
    triangulate(image, feature_points[i])

warp(img2, feature_points[0], feature_points[1])

扭曲.py

import numpy as np
import cv2 as cv

def triangulate(image, points):

    # Create Subdiv2D object
    rect = (0, 0, image.shape[0], image.shape[1])  # Rectangle covering the entire image
    triangulation = cv.Subdiv2D(rect)

      # Insert points into triangulation object
    valid_points = []  # List to store valid points within the image bounds
    for point in points:
        x, y = point
        if 0 <= x < image.shape[1] and 0 <= y < image.shape[0]:  # Check if point is within image bounds
            triangulation.insert((x, y))
            valid_points.append((x, y))
        
    # Get triangles
    triangleList1 = triangulation.getTriangleList()

    # Draw triangles on the image (optional)
    for t in triangleList1:
        pt1 = (int(t[0]), int(t[1]))
        pt2 = (int(t[2]), int(t[3]))
        pt3 = (int(t[4]), int(t[5]))
        cv.line(image, pt1, pt2, (0, 255, 0), 1, cv.LINE_AA)
        cv.line(image, pt2, pt3, (0, 255, 0), 1, cv.LINE_AA)
        cv.line(image, pt3, pt1, (0, 255, 0), 1, cv.LINE_AA)

    # Show or return the triangulated image (optional)
    cv.imshow('Triangulated Image', image)
    cv.waitKey(0)
    cv.destroyAllWindows()

    return valid_points

def warp(image, points1, points2):
    # Compute affine transformation matrix
    M = cv.getAffineTransform(np.float32(points1), np.float32(points2))

    # Warp image1 onto image2
    rows, cols, _ = image.shape
    warped_image = cv.warpAffine(image, M, (cols, rows))

    # Display or save the warped image
    cv.imshow('Warped Image', warped_image)
    cv.waitKey(0)
    cv.destroyAllWindows()

收到此错误

    M = cv.getAffineTransform(np.float32(points1), np.float32(points2))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cv2.error: OpenCV(4.9.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\imgwarp.cpp:3554: error: (-215:Assertion failed) src.checkVector(2, CV_32F) == 3 && dst.checkVector(2, CV_32F) == 3 in function 'cv::getAffineTransform'
python image opencv image-processing
1个回答
0
投票

我的问题的解决方案是这样的:

img1 = './Images/mulher1.jpg'
img2 = './Images/homem.jpg'

feature_points, cropped_images = generate_face_correspondeces(img1, img2)

img_shape = []

for i, image in enumerate(cropped_images):
    triangulate(image, feature_points[i])

    img_shape.append((image.shape[1], image.shape[0]))

src_pts = np.asarray(feature_points[1], dtype=np.float32)
dst_pts = np.asarray(feature_points[0], dtype=np.float32)

transformMatrix = cv.estimateAffine2D(src_pts, dst_pts)

warped_img = cv.warpAffine(cropped_images[1], transformMatrix[0], img_shape[0])

cv.imshow("img", warped_img)
cv.waitKey(0)
© www.soinside.com 2019 - 2024. All rights reserved.