Python 在opencv中如何使用仿射变换实现这一点?

Python 在opencv中如何使用仿射变换实现这一点?,python,image,opencv,Python,Image,Opencv,我想知道如何复制此图像中正在执行的操作: 要分解它: 使用dlib(绿点)获取面部标志 旋转图像,使眼睛水平 通过平均最左侧和最右侧的地标(蓝点)找到面部的中点,并将图像置于x轴的中心 通过将眼睛中心距图像顶部45%,嘴中心距图像25%,沿y轴固定位置 这就是我现在所拥有的: 我被第三步卡住了,我想这可以通过仿射变换来完成?但我完全被第四步难住了,我不知道我该如何实现它 如果您需要我提供代码,请告诉我 编辑:所以在看了@Gal Dreiman的答案后,我能够完美地将脸部居中,这样蓝色的圆点就

我想知道如何复制此图像中正在执行的操作:

要分解它:

  • 使用dlib(绿点)获取面部标志
  • 旋转图像,使眼睛水平
  • 通过平均最左侧和最右侧的地标(蓝点)找到面部的中点,并将图像置于x轴的中心
  • 通过将眼睛中心距图像顶部45%,嘴中心距图像25%,沿y轴固定位置
  • 这就是我现在所拥有的:

    我被第三步卡住了,我想这可以通过仿射变换来完成?但我完全被第四步难住了,我不知道我该如何实现它

    如果您需要我提供代码,请告诉我

    编辑:所以在看了@Gal Dreiman的答案后,我能够完美地将脸部居中,这样蓝色的圆点就位于我的图像的中心

    虽然当我实施他的答案的第二部分时,我最终得到了如下结果:

    我看到这些点已经被转换到了正确的位置,但这并不是我所期望的结果,因为它非常引人注目。有什么想法吗

    编辑2:

    切换周围中心点的x,y坐标后,我得到:


    正如我在第3节中看到的,最简单的方法是:

  • 在图像中查找面:

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags = cv2.cv.CV_HAAR_SCALE_IMAGE
    )
    
  • 对于每个面,计算中点:

    for (x, y, w, h) in faces:
        mid_x = x + int(w/2)
        mid_y = y + int(h/2)
    
  • 对图像进行仿射变换以使已计算的蓝点居中:

    height, width = img.shape
    x_dot = ...
    y_dot = ...
    
    dx_dot = int(width/2) - x_dot
    dy_dot = int(height/2) - y_dot
    
    M = np.float32([[1,0,dx_dot],[0,1,dy_dot]])
    dst = cv2.warpAffine(img,M,(cols,rows))
    
  • 希望能有所帮助

    编辑:

    关于第4节: 为了拉伸(调整大小)图像,您所要做的就是执行仿射变换。为了找到变换矩阵,我们需要从输入图像中提取三个点及其在输出图像中的相应位置

        p_1 = [eyes_x, eye_y]
        p_2 = [int(width/2),int(height/2)] # default: center of the image
        p_3 = [mouth_x, mouth_y]
    
        target_p_1 = [eyes_x, int(eye_y * 0.45)]
        target_p_2 = [int(width/2),int(height/2)] # don't want to change
        target_p_3 = [mouth_x, int(mouth_y * 0.75)]
    
        pts1 = np.float32([p_1,p_2,p_3])
        pts2 = np.float32([target_p_1,target_p_2,target_p_3])
    
        M = cv2.getAffineTransform(pts1,pts2)
    
        output = cv2.warpAffine(image,M,(height,width))
    
    要解决问题:

  • eye_x
    /
    eye_y
    是眼睛中心的位置
  • 这同样适用于嘴中心的
    嘴x
    /
    嘴y
  • target\u p\u 1/2/3
    是目标点
  • 编辑2: 我看你有麻烦了,我希望这次我的建议对你有用:

    我可以想到另一种方法。您可以通过指向4个点对图像执行排序“裁剪”,将它们定义为包裹面的4个点,并根据它们的新位置更改图像透视图:

    up_left = [x,y]
    up_right = [...]
    down_left = [...]
    down_right = [...]
    
    pts1 = np.float32([up_left,up_right,down_left,down_right])
    pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
    
    M = cv2.getPerspectiveTransform(pts1,pts2)
    
    dst = cv2.warpPerspective(img,M,(300,300))
    

    所以你要做的就是定义这4个点。我的建议是,计算脸部周围的conture(你已经计算过了),然后将
    delta_x
    delta_y
    (或减法)添加到坐标中。

    谢谢你让我的图像居中!你对第四步有什么想法吗?我该如何缩放我的图像,使脸部和嘴巴处于正确的位置?谢谢好心的先生
    @Gal Dreimand
    你介意看一下我更新的问题吗,我已经成功地将面部居中,但调整形状的过程并不像预期的那样进行。如果你仍然感兴趣,请添加一个悬赏:)抱歉耽搁了。我在你的更新中看到,根据你的源点,目标点是正确的:你只想改变y轴:那么为什么你的中心点改变了(可能不是第一个点)?