python MachinelEarning机器学习笔记day07

day07-特征值矩阵-识别图片中的物体-视频捕捉-人脸定位-人脸识别的分类器    
        6.特征值矩阵(描述矩阵)
            特征值矩阵 = STAR特征点(位置,大小)+SIFT(方向)
            代码示例:desc.py
                import cv2 as cv
                import matplotlib.pyplot as mp
                original = cv.imread('../../day01/data/table.jpg')
                cv.imshow('or ',original)
                gray = cv.cvtColor(original,cv.COLOR_BGR2GRAY)
                cv.imshow('gr ',gray)
                star = cv.xfeatures2d.StarDetector_create()
                keystar = star.detect(gray)
                sift = cv.xfeatures2d.SIFT_create() #需使用3.4.2.16版本:pip install opencv-contrib-python==3.4.2.16
                _,desc = sift.compute(gray,keystar)
                print(desc.shape)
                mp.matshow(desc,cmap='jet',fignum='Desc')
                mp.title('Desc',fontsize=20)
                mp.xlabel('Feature',fontsize=14)
                mp.ylabel('Sample',fontsize=14)
                mp.tick_params(which='both',top=False,labeltop=False,
                                             labelbottom=True,labelsize=10)
                mp.tight_layout()
                mp.show()
                cv.waitKey()
        7.识别图片中的物体
            代码示例:obj.py
                import cv2 as cv
                import os
                import warnings
                import numpy as np
                import hmmlearn.hmm as hl
                warnings.filterwarnings('ignore',category=DeprecationWarning)
                np.seterr(all='ignore')
                def search_obj(directory):
                        directory = os.path.normpath(directory)
                        if not os.path.isdir(directory):
                             raise IOError("目录不存在:"+ directory)
                        obj = {}
                        for curdir,subdirs,files in os.walk(directory): #遍历目录
                             for jpeg in (file for file in files if file.endswith('.jpg')):
                                     path = os.path.join(curdir,jpeg)
                                     label = path.split(os.path.sep)[-2]#获得图片当前目录名称
                                     if label not in obj:
                                             obj[label] = []
                                     obj[label].append(path)
                        return obj
                train_objs = search_obj('../../day01/data/objects/training')
                train_x,train_y = [],[]
                for label,filenames in train_objs.items():
                        descs = np.array([])
                        for filename in filenames:
                                image = cv.imread(filename)
                                gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
                                h,w = gray.shape[:2] #取得图片高度(行)和宽度(列)
                                f = 200 / min(h,w) #方便统一尺寸,以高宽最小值作为缩放小比例
                                gray = cv.resize(gray,None,fx=f,fy=f)#高宽等比缩放图片
                                star = cv.xfeatures2d.StarDetector_create()
                                keypoints = star.detect(gray)
                                sift = cv.xfeatures2d.SIFT_create()
                                _,desc = sift.compute(gray,keypoints)
                                if len(descs) == 0:
                                        descs = desc
                                else:
                                        descs = np.append(descs,desc,axis=0)
                        train_x.append(descs)
                        train_y.append(label)
                models = {}
                for descs,label in zip(train_x,train_y):
                        model = hl.GaussianHMM(n_components=4,covariance_type='diag',n_iter=1000)
                        models[label] = model.fit(descs) #训练模型
                #以下测试模型
                test_objs = search_obj('../../day01/data/objects/testing')
                test_x,test_y,test_img = [],[],[]
                for label,filenames in test_objs.items():
                        test_img.append([])
                        descs = np.array([])
                        for filename in filenames:
                                image = cv.imread(filename)
                                test_img[-1].append(image)
                                gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
                                h,w = gray.shape[:2] #取得图片高度(行)和宽度(列)
                                f = 200 / min(h,w) #方便统一尺寸,以高宽最小值作为缩放小比例
                                gray = cv.resize(gray,None,fx=f,fy=f)#高宽等比缩放图片
                                star = cv.xfeatures2d.StarDetector_create()
                                keypoints = star.detect(gray)
                                sift = cv.xfeatures2d.SIFT_create()
                                _,desc = sift.compute(gray,keypoints)
                                if len(descs) == 0:
                                        descs = desc
                                else:
                                        descs = np.append(descs,desc,axis=0)
                        test_x.append(descs)
                        test_y.append(label)
                pred_test_y = []#保存预测/测试结果
                for descs in test_x:
                        best_score,best_label = None,None
                        for label,model in models.items():
                                score = model.score(descs)
                                if (best_score is None) or (best_score < score):
                                        best_score,best_label = score,label
                        pred_test_y.append(best_label)
                #以下输出预测结果
                i = 0
                for label,pred_label,images in zip(test_y,pred_test_y,test_img):
                        for image in images:
                                i += 1
                                cv.imshow('{}-{} {} {}'.format(i,label,
                                        '==' if label == pred_label else '!=',pred_label),image)
                cv.waitKey()
    十七、人脸识别
        1.视频捕捉
            捕捉设备-->图像帧
            代码示例:vidcap.py
                import cv2 as cv
                vc = cv.VideoCapture(0) #视频捕捉,设备ID为从0开始的整数,0,是第一个,1是第二个,也可同时打开多摄像头
                while True:
                        frame = vc.read()[1] #获得一个图片帧
                        cv.imshow('VideoCapture',frame)
                        if cv.waitKey(33) == 27: #27:是esc键。33表示等待33毫秒,相当于每秒连续显示33张图片
                                break
                vc.release()#一般摄像头是独占式,用完需释放
                cv.destroyAllWindows()#释放隐藏窗口
        2.人脸定位
            哈儿级联人脸定位
            cv.CascadeClassifier(xml参数文件)对象检测,如无参数文件,自动调用该函数分配初始参数
                cv.CascadeClassifier('./face.xml')#脸部定位器
                cv.CascadeClassifier('./eye.xml')#眼睛定位器
                cv.CascadeClassifier('./nose.xml')#鼻子定位器            
            fd.detectMultiScale(原图,图片最小尺寸,抓取图片最大数量)级联分类器
                获得人脸轮廓集合,每张图片一个元组,元组内包括脸的左边点坐标,顶点坐标,宽度,高度,形成元组列表返回。
                图片最小尺寸:指原图的最小尺寸(厘米),低于尺寸不抓取。
                抓取图片最大数量:指有效图片的数量。  
                ed.detectMultiScale(face,1.3,5)#在脸中定位眼睛,返回眼睛的外切矩形
                nd.detectMultiScale(face,1.3,5)#在脸中定位鼻子,返回鼻子的外切矩形
            cvEllipse(img, CvPoint center, CvSize axes, double angle, 
                double start_angle, double end_angle, CvScalar color, 
                int thickness=1, int line_type=8, int shift=0 )
                Ellipse绘制椭圆圆弧和椭圆扇形
                center--椭圆圆心坐标。axes--轴(半径)的长度。
                angle--偏转的角度。start_angle--圆弧起始角的角度。
                end_angle--圆弧终止角的角度。color--线条的颜色。
                thickness--线条的粗细程度。
                line_type--线条的类型,8 (or 0) - 8-connected line(8邻接)连接线。
                                                            4 - 4-connected line(4邻接)连接线。
                shift--圆心坐标点和数轴的精度。
            代码示例:haar.py
                import cv2 as cv
                # CascadeClassifier哈儿级联人脸定位器 face.xm为参数文件
                fd = cv.CascadeClassifier('../../day01/data/haar/face.xml')#脸部定位器
                ed = cv.CascadeClassifier('../../day01/data/haar/eye.xml')#眼睛定位器
                nd = cv.CascadeClassifier('../../day01/data/haar/nose.xml')#鼻子定位器
                vc = cv.VideoCapture(0) #视频捕捉,设备ID为从0开始的整数,0,是第一个,1是第二个,也可同时打开多摄像头
                while True:
                        frame = vc.read()[1] #获得一个图片帧
                        # detectMultiScale级联分类器,人脸轮廓集合,1.3图片大小(厘米)下限,5,最多获取图片数量
                        faces = fd.detectMultiScale(frame,1.3,5) #获得每张矩形框脸的元组(左顶宽高四个点),形成元组列表返回。
                        for l,t,w,h in faces:
                                a , b = int(w/2),int(h/2) #用于在大图中绘制脸部的椭圆框
                                cv.ellipse(frame,(l+a,t+b),(a,b),0,0,360,(255,0,255),2)
                                face = frame[t:t+h,l:l+w] #将脸部取出
                                eyes = ed.detectMultiScale(face,1.3,5)#在脸中定位眼睛,返回眼睛的外切矩形
                                for l,t,w,h in eyes:
                                        a, b = int(w / 2), int(h / 2)  # 用于在脸的图片上绘制眼睛的椭圆框
                                        cv.ellipse(face, (l + a, t + b), (a, b), 0, 0, 360, (0, 255, 0), 2)
                                nose = nd.detectMultiScale(face,1.3,5)#在脸中定位鼻子,返回鼻子的外切矩形
                                for l,t,w,h in nose:
                                        a, b = int(w / 2), int(h / 2)  # 用于在脸的图片上绘制鼻子的椭圆框
                                        cv.ellipse(face, (l + a, t + b), (a, b), 0, 0, 360, (255, 0, 0), 2)
                        cv.imshow('VideoCapture',frame)
                        if cv.waitKey(33) == 27: #27:是esc键。33表示等待33毫秒,相当于每秒连续显示33张图片
                                break
                vc.release()#一般摄像头是独占式,用完需释放
                cv.destroyAllWindows()#释放隐藏窗口
        3.简单人脸识别
            OpenCV的LBPH:局部二值模式直方图 
            代码示例:face.py
                import cv2 as cv
                import os
                import numpy as np
                import sklearn.preprocessing as sp
                fd = cv.CascadeClassifier('../../day01/data/haar/face.xml')
                def search_faces(directory):
                        directory = os.path.normpath(directory)
                        if not os.path.isdir(directory):
                             raise IOError("目录不存在:"+ directory)
                        faces = {}
                        for curdir,subdirs,files in os.walk(directory): #遍历目录
                                for jpeg in (file for file in files if file.endswith('.jpg')):
                                        path = os.path.join(curdir,jpeg)
                                        label = path.split(os.path.sep)[-2]#获得图片当前目录名称
                                        if label not in faces:
                                                faces[label] = []
                                        faces[label].append(path)
                        return faces
                train_faces = search_faces('../../day01/data/faces/training')
                codec = sp.LabelEncoder()#标签编码器
                codec.fit(list(train_faces.keys()))#转换为编码字典
                train_x,train_y = [],[]
                for label,filenames in train_faces.items():
                        for filename in filenames:
                                image = cv.imread(filename)
                                gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
                                #比minSize(像素)还小的尺寸,忽略。
                                faces = fd.detectMultiScale(gray,1.1,3,minSize=(100,100)) #定位脸部
                                for l,t,w,h in faces:
                                        train_x.append(gray[t:t+h,l:l+w])#外切脸部
                                        train_y.append(codec.transform([label])[0])
                train_y = np.array(train_y)
                model = cv.face.LBPHFaceRecognizer_create()#局部二值模式直方图人脸识别器
                model.train(train_x,train_y)#训练模型
                #以下模型测试/预测
                test_faces = search_faces('../../day01/data/faces/testing')
                test_x,test_y,test_img = [],[],[]
                for label,filenames in test_faces.items():
                        for filename in filenames:
                                image = cv.imread(filename)
                                gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
                                #比minSize(像素)还小的尺寸,忽略。
                                faces = fd.detectMultiScale(gray,1.1,2,minSize=(100,100)) #定位脸部
                                for l,t,w,h in faces:
                                        test_x.append(gray[t:t+h,l:l+w])#外切脸部
                                        test_y.append(codec.transform([label])[0])
                                        a,b = int(w/2),int(h/2)
                                        cv.ellipse(image,(l+a,t+b),(a,b),0,0,360,(255,0,255),2)
                                        test_img.append(image)
                test_y = np.array(test_y)
                #输出预测结果
                pred_test_y = []
                for face in test_x:
                        pred_code = model.predict(face)[0]
                        pred_test_y.append(pred_code)
                escape = False
                while not escape:
                        for code,pred_code,image in zip(test_y,pred_test_y,test_img):
                                label,pred_label = codec.inverse_transform([code,pred_code])
                                text = '{} {} {}'.format(label,'=='if code == pred_code else '!=',
                                                                                 pred_label)
                                cv.putText(image,text,(10,60),cv.FONT_HERSHEY_SIMPLEX,2,(255,255,255),6)
                                cv.imshow('waiting...',image)
                                if cv.waitKey(1000)==27:
                                        escape = True
                                        break
        4.基于通用分类器的人脸识别
            1).显示数据集
                代码示例:face1.py
                    import sklearn.datasets as sd
                    import matplotlib.pyplot as mp
                    faces = sd.fetch_olivetti_faces('../../day01/data/')
                    x, y  = faces.data , faces.target
                    #print(x.shape,x.dtype,y.shape,set(y))
                    mp.figure('Olivette',facecolor='black')
                    mp.subplots_adjust(left=0.04,bottom=0.04,right=0.96,top=0.96,
                                                         wspace=0,hspace=0)#设定各子图边距与间隔,按百分数计算
                    rows,cols = 10,40
                    for row in range(rows):
                            for col in range(cols):
                                    mp.subplot(rows,cols,row * cols + col + 1)
                                    if row==0:
                                            mp.title(str(col),fontsize=8,color='limegreen')
                                    if col == 0:
                                            mp.ylabel(str(row),fontsize=8,color='limegreen')
                                    mp.xticks(())
                                    mp.yticks(())
                                    image = x[y==col][row].reshape(64,64)
                                    mp.imshow(image,cmap='gray')
                    mp.show()
            2).用SVM分类器实现人脸识别
                代码示例:face2.py
                    import sklearn.datasets as sd
                    import sklearn.model_selection as ms
                    import sklearn.svm as svm
                    import sklearn.metrics as sm
                    import matplotlib.pyplot as mp
                    faces = sd.fetch_olivetti_faces('../../day01/data/')
                    x, y  = faces.data , faces.target
                    #print(x.shape,x.dtype,y.shape,set(y))
                    train_x,test_x,train_y,test_y = ms.train_test_split(x,y,test_size=0.2,random_state=7)
                    model = svm.SVC(class_weight='balanced')
                    model.fit(train_x,train_y)
                    pred_test_y = model.predict(test_x)
                    cm = sm.confusion_matrix(test_y,pred_test_y)
                    cr = sm.classification_report(test_y,pred_test_y)
                    print(cr)#打印输出分类报告 #结果很差,F1打分为9%,数据问题?
                    mp.figure('Confusion_matrix',facecolor='black')
                    mp.title('Confusion_matrix',fontsize=20)
                    mp.xlabel('Predicted',fontsize=14)
                    mp.ylabel('TrueClass',fontsize=14)
                    mp.tick_params(labelsize=10)
                    mp.imshow(cm ,interpolation= 'nearest',cmap='gray')
                    mp.show()
            3).主成分分析(PCA)降维
                代码示例:pca1.py  numpy 降维
                    import numpy as np
                    #原始样本
                    A = np.mat('3 2000;2 3000;4 5000;5 8000;1 2000',dtype=float)
                    print('A=',A,sep='\n')
                    #降维:归一化缩放,每列均值为0,范围在0-1之间
                    mu = A.mean(axis=0) #求各列平均值
                    s = A.max(axis=0) - A.min(axis=0)
                    X = (A - mu ) /s
                    print('X=',X,sep='\n')
                    #协方差矩阵
                    SIGMA = X.T * X
                    print(SIGMA)
                    #奇异值分解
                    U,S,V = np.linalg.svd(SIGMA)
                    print('U=',U,sep='\n')
                    #主成分特征矩阵
                    U_reduce = U[:,0]
                    print('U_reduce',U_reduce,sep='\n')
                    #获得降维样本
                    Z = X * U_reduce
                    print('Z=',Z,sep='\n')
                    #降维样本恢复
                    #1、恢复归一缩放样本(近似恢复)
                    X_approx = Z * U_reduce.T
                    print('X_approx',X_approx,sep='\n')
                    #2、近似恢复原样本A
                    A_approx = np.multiply(X_approx,s) + mu
                    print('A_approx',A_approx,sep='\n')
                代码示例:pca2.py  sklearn.decomposition
                    import numpy as np
                    import sklearn.pipeline as pl
                    import sklearn.preprocessing as sp
                    import sklearn.decomposition as dc #降维工具
                    #原始样本
                    A = np.mat('3 2000;2 3000;4 5000;5 8000;1 2000',dtype=float)
                    print('A=',A,sep='\n')
                    #构建PCA模型
                    #MinMaxScaler做归一化缩放
                    #PCA(n_components=1)降维
                    model = pl.Pipeline([('scaler',sp.MinMaxScaler()),('pca',dc.PCA(n_components=1))])
                    #降维样本
                    Z = model.fit_transform(A)
                    print('Z=',Z,sep='\n')
                    #近视恢复到原始样本
                    A_approx = model.inverse_transform(Z)
                    print('A_approx',A_approx,sep='\n')
            4).还原率
                进过PCA降维后的样本,再进行逆向还原,与原始样本相比的误差
                代码示例:face3.py
                    import sklearn.datasets as sd
                    import sklearn.decomposition as dc
                    import matplotlib.pyplot as mp
                    faces = sd.fetch_olivetti_faces('../../day01/data/')
                    x, y  = faces.data , faces.target
                    #print(x.shape,x.dtype,y.shape,set(y))
                    ncps = range(10,410,10)
                    evrs = []
                    for ncp in ncps:
                            model = dc.PCA(n_components=ncp)
                            model.fit_transform(x)
                            evr = model.explained_variance_ratio_.sum() #还原率误差
                            evrs.append(evr)
                    mp.figure('explained_variance_ratio',facecolor='black')
                    mp.title('explained_variance_ratio',fontsize=20)
                    mp.xlabel('n_components',fontsize=14)
                    mp.ylabel('explained_variance_ratio',fontsize=14)
                    mp.tick_params(labelsize=10)
                    mp.grid(linestyle=':')
                    mp.plot(ncps,evrs,c='dodgerblue',label='explained_variance_ratio')
                    mp.legend()
                    mp.show()
                代码示例:face4.py
                    import sklearn.datasets as sd
                    import sklearn.decomposition as dc
                    import matplotlib.pyplot as mp
                    faces = sd.fetch_olivetti_faces('../../day01/data/')
                    x, y  = faces.data , faces.target
                    #print(x.shape,x.dtype,y.shape,set(y))
                    mp.figure('explained_variance_ratio',facecolor='black')
                    mp.subplots_adjust(left=0.04,bottom=0.04,right=0.96,top=0.96,
                                                         wspace=0,hspace=0)#设定各子图边距与间隔,按百分数计算
                    rows,cols = 11,40
                    for row in range(rows):
                            if row > 0 :
                                    ncp = 140 - (row -1) * 15
                                    model = dc.PCA(n_components=ncp)
                                    model.fit(x)
                            for col in range(cols):
                                    mp.subplot(rows,cols,row * cols + col + 1)
                                    if row==0:
                                            mp.title(str(col),fontsize=8,color='limegreen')
                                    if col == 0:
                                            mp.ylabel(str(ncp) if row > 0 else 'orig',fontsize=8,color='limegreen')
                                    mp.xticks(())
                                    mp.yticks(())
                                    if row > 0:
                                            pca_x = model.transform([x[y==col][0]])
                                            ipca_x = model.inverse_transform(pca_x) #还原
                                            image = ipca_x.reshape(64,64)
                                    else:
                                            image = x[y==col][0].reshape(64,64)
                                    mp.imshow(image,cmap='gray')#显示还原后的图片
                    mp.show()
            5).用PCA降维改善基于SVM分类器的人脸识别效果    
                代码示例:face5.py  与face2.py对比后,效果大幅提升
                    import sklearn.datasets as sd
                    import sklearn.decomposition as dc
                    import sklearn.model_selection as ms
                    import sklearn.svm as svm
                    import sklearn.metrics as sm
                    import matplotlib.pyplot as mp
                    faces = sd.fetch_olivetti_faces('../../day01/data/')
                    x, y  = faces.data , faces.target
                    #print(x.shape,x.dtype,y.shape,set(y))
                    model = dc.PCA(n_components=140)
                    pca_x = model.fit_transform(x)
                    #print(x.shape,pca_x.shape)
                    train_x,test_x,train_y,test_y = ms.train_test_split(pca_x,y,test_size=0.2,random_state=7)
                    model = svm.SVC(class_weight='balanced')
                    model.fit(train_x,train_y)
                    pred_test_y = model.predict(test_x)
                    cm = sm.confusion_matrix(test_y,pred_test_y)
                    cr = sm.classification_report(test_y,pred_test_y)
                    print(cr)#打印输出分类报告 #结果很差,F1打分为9%,数据问题?
                    mp.figure('Confusion_matrix',facecolor='black')
                    mp.title('Confusion_matrix',fontsize=20)
                    mp.xlabel('Predicted',fontsize=14)
                    mp.ylabel('TrueClass',fontsize=14)
                    mp.tick_params(labelsize=10)
                    mp.imshow(cm ,interpolation= 'nearest',cmap='gray')
                    mp.show()
            6).核主成分分析(KPCA) 
                先升维    再降维
                对于在原始维度空间无法线性分割的样本,利用核函数升高
                维度,力图在更高纬度空间线性可分,而后再选择适当的与
                原始维度相同的空间做反向投影,得到低纬度空间线性可分的样本集。
                代码示例:kpca.py
                    import sklearn.datasets as sd
                    import sklearn.decomposition as dc
                    import matplotlib.pyplot as mp
                    x,y = sd.make_circles(n_samples=500,factor=0.2,noise=0.04)
                    model = dc.KernelPCA(kernel='rbf',gamma=1) #升维
                    kpca_x = model.fit_transform(x)[:,:x.shape[1]]
                    mp.figure('Original',facecolor='lightgray')
                    mp.title('Original',fontsize=20)
                    mp.xlabel('x',fontsize=14)
                    mp.ylabel('y',fontsize=14)
                    mp.tick_params(labelsize=10)
                    mp.grid(linestyle=':')
                    mp.scatter(x[:,0],x[:,1],c=y,cmap='brg',alpha=0.5,s=60)
                    mp.figure('KPCA',facecolor='lightgray')
                    mp.title('KPCA',fontsize=20)
                    mp.xlabel('x',fontsize=14)
                    mp.ylabel('y',fontsize=14)
                    mp.tick_params(labelsize=10)
                    mp.grid(linestyle=':')
                    mp.scatter(kpca_x[:,0],kpca_x[:,1],c=y,cmap='brg',alpha=0.5,s=60)
                    mp.show()
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值