小练习:OpenCV的简单应用---手动提取人脸特征点

  • 简述:
    基于OpenCV中的基本方法,进行人脸区域的矫正切割,采用了68个定位点中的左眼,右眼,嘴巴中心这三个定位点进行提取,使用输入,输出图像构成的三组点对,利用仿射变换,实现最终图像的输出。
import cv2
import glob
import os
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['simhei'] # 添加中文字体为简黑
plt.rcParams['axes.unicode_minus'] =False

point_in = list()
#导入照片文件列表
def load_image(path_in):
    type_list = ['*.png','*.jpg','*.jpeg']
    img_list = list()
    for i in type_list:img_list+=glob.glob(path_in+i)
    return img_list

#点击事件的回调函数
def on_EVENT_LBUTTONDOWN(event,x,y,flags,param):
    global point_in
    imgIn0= param
    a = len(point_in)
    if a<3:
        if event == cv2.EVENT_LBUTTONDOWN:
            point_in.append([x,y])
            cv2.circle(imgIn0,(x,y),3, (255, 0, 0), thickness = -1) #画圆半径为3,并填充
            cv2.putText(imgIn0, str(a + 1), (x, y), cv2.FONT_HERSHEY_PLAIN,
                        1.0, (0, 255, 0), thickness=1) #加入文字,位置,字体,尺度因子,颜色,粗细
            cv2.imshow("window 2", imgIn0)

def show_image(img_list,path_out,point_in):
    for i,img_path in enumerate(img_list):
        point_in.clear()
        # A.以灰度模式读取原始图像、可视化
        # cv2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写1。
        # cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写0。
        # cv2.IMREAD_UNCHANGED:包括alpha,可以直接写-1

        imgIn = cv2.imread(img_path,1)
        imgIn0= imgIn.copy() #形成image对象

        rows, cols, channels = imgIn0.shape #d读取输入图像行数,列数,颜色通道
        print('第%d幅图:'%i,rows, cols, channels)
        cv2.namedWindow("window 1", flags=cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)#窗口命名,并大小可变
        cv2.imshow("window 1", imgIn)

        cv2.namedWindow("window 2", flags=cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)
        cv2.imshow("window 2", imgIn0)
        cv2.setMouseCallback("window 2", on_EVENT_LBUTTONDOWN,imgIn0)#手动点击进行特征点的提取


        cv2.waitKey(0)  #等待键盘点击事件来结束阻塞
        print(point_in)

        point_out = np.float32([[25, 30], [75, 30], [50, 75]])#左眼,右眼,嘴巴中心的特征点的坐标
        # 估计由输出坐标到输入坐标的放射变换模型
        M = cv2.getAffineTransform(np.float32(point_in), point_out)
        print(M)
        rows2,cols2 = 100,100 #指定输出图像的大小
        
        #利用仿射变换模型,将输入图像仿射变换,产生输出图像
        imgOut = cv2.warpAffine(imgIn, M, (cols2, rows2))
        b, g, r = cv2.split(imgOut) #opencv 颜色读取方式为bgr
        img2 = cv2.merge([r, g, b])  #plt则是rgb
        plt.imshow(img2)
        plt.show()

        image_name = os.path.splitext(os.path.split(img_path)[1])[0] #获取文件名
        cv2.imwrite(path_out+image_name+'_out.jpg',imgOut)   #保存矫正后的人脸图片

        print('*'*20 )
        cv2.destroyAllWindows() #销毁所有窗口

if __name__ == '__main__':
    path_in = r'imageIN/'
    path_out = r'imageOUT/'

    img_list=load_image(path_in)
    show_image(img_list,path_out,point_in)

输入图像
在这里插入图片描述
输出图像:
在这里插入图片描述
代码执行结果

第0幅图: 373 360 3
[[358, 25], [170, 170], [215, 221]]
[[-3.83230932e-01 -1.52051139e-01  1.65997952e+02]
 [ 4.04952523e-01  5.25041892e-01 -1.28099050e+02]]
********************
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值