导航:首页 > 编程语言 > 人脸纹理变换代码

人脸纹理变换代码

发布时间:2023-05-05 13:06:49

㈠ opengl es怎么实现纹理变化

呃,提供一个思路还不够啊....好吧,看着你在群里支持le3d的友情上,给你写段伪代码~~(0)在类的成员函数里,定义一个int textureId,作为纹理的id;(1)在核橡onsurfacecreated相关初始化的函数里,创建一张纹理1.1 glGenTexture申请一个id1.2 bind texture1.3 glTexImage()分配一张空纹理1.4 set texture parameter 设置纹理相关参扒拍数(2)在onDrawFrame等回调函数里2.1 bind texture帮顶纹理2.2 glTexSubImage更新改此旁纹理,用你每帧截取的画面2.3 绘制(3)在onsurfacedestroyed相关函数,释放资源。

㈡ uniform lbp算子进行人脸识别得到的图像整体偏

uniform lbp算子进行人脸识别得到的图像整体偏是:是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度级不变性等显著的优点。

它是首先由T. Ojala, M.Pietikäinen, 和 D. Harwood 在1994年提出,用于纹理特征提取。而且,提取的特征是图像的局部的纹理特征。

并且原始的LBP算子定义为在3*3的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。

这样,3*3领域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理信息。

LBP等价模式是:

一个LBP算子可以产生不同的二进制模式,对于半径为R的圆形区域内含有P个采样点的LBP算子将会产生P2种模式。很显然,随着邻域集内采样点数的增加,二进制模式的种类是急剧增加的。

例如:5×5邻域内20个采样点,有220=1,048,576种二进制模式。如此多的二值模式无论对于纹理的提取还是对于纹理的识别、分类及信息的存取都是不利的。

同时,过多的模式种类对于纹理的表达是不利的。例如,将LBP算子用于纹理分类或人脸识别时,常采用LBP模式的统计直方图来表达图像的信息,而较多的模式种类将使得数据量过大。

且直方图过于稀疏。因此,需要对原始的LBP模式进行降维,使得数据量减少的情况下能最好的代表图像的信息。

㈢ 求gabor滤波器分析图像纹理的c++程序 opencv的就不要了

整个项目的结构图:

编写DetectFaceDemo.java,代码如下:

[java] view
plainprint?

package com.njupt.zhb.test;

import org.opencv.core.Core;

import org.opencv.core.Mat;

import org.opencv.core.MatOfRect;

import org.opencv.core.Point;

import org.opencv.core.Rect;

import org.opencv.core.Scalar;

import org.opencv.highgui.Highgui;

import org.opencv.objdetect.CascadeClassifier;

//

// Detects faces in an image, draws boxes around them, and writes the results

// to "faceDetection.png".

//

public class DetectFaceDemo {

public void run() {

System.out.println("\nRunning DetectFaceDemo");

System.out.println(getClass().getResource("lbpcascade_frontalface.xml").getPath());

// Create a face detector from the cascade file in the resources

// directory.

//CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("森段并lbpcascade_frontalface.xml").getPath());

//Mat image = Highgui.imread(getClass().getResource("lena.png").getPath());

//注意:源程序的路径会多打印一个燃竖‘/’,因此总是出现如下错误

/*

* Detected 0 faces Writing faceDetection.png libpng warning: Image

* width is zero in IHDR libpng warning: Image height is zero in IHDR

* libpng error: Invalid IHDR data

*/

//因此,我们将第一个字符去掉

String xmlfilePath=getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);

CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);

Mat image = Highgui.imread(getClass().getResource("we.jpg").getPath().substring(1));

// Detect faces in the image.

// MatOfRect is a special container class for Rect.

MatOfRect faceDetections = new MatOfRect();

faceDetector.detectMultiScale(image, faceDetections);

System.out.println(String.format("此迹Detected %s faces", faceDetections.toArray().length));

// Draw a bounding box around each face.

for (Rect rect : faceDetections.toArray()) {

Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));

}

// Save the visualized detection.

String filename = "faceDetection.png";

System.out.println(String.format("Writing %s", filename));

Highgui.imwrite(filename, image);

}

}
package com.njupt.zhb.test;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.objdetect.CascadeClassifier;

//
// Detects faces in an image, draws boxes around them, and writes the results
// to "faceDetection.png".
//
public class DetectFaceDemo {
public void run() {
System.out.println("\nRunning DetectFaceDemo");
System.out.println(getClass().getResource("lbpcascade_frontalface.xml").getPath());
// Create a face detector from the cascade file in the resources
// directory.
//CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("lbpcascade_frontalface.xml").getPath());
//Mat image = Highgui.imread(getClass().getResource("lena.png").getPath());
//注意:源程序的路径会多打印一个‘/’,因此总是出现如下错误
/*
* Detected 0 faces Writing faceDetection.png libpng warning: Image
* width is zero in IHDR libpng warning: Image height is zero in IHDR
* libpng error: Invalid IHDR data
*/
//因此,我们将第一个字符去掉
String xmlfilePath=getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);
CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);
Mat image = Highgui.imread(getClass().getResource("we.jpg").getPath().substring(1));
// Detect faces in the image.
// MatOfRect is a special container class for Rect.
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(image, faceDetections);

System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));

// Draw a bounding box around each face.
for (Rect rect : faceDetections.toArray()) {
Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
}

// Save the visualized detection.
String filename = "faceDetection.png";
System.out.println(String.format("Writing %s", filename));
Highgui.imwrite(filename, image);
}
}

3.编写测试类:

[java] view
plainprint?

package com.njupt.zhb.test;

public class TestMain {

public static void main(String[] args) {

System.out.println("Hello, OpenCV");

// Load the native library.

System.loadLibrary("opencv_java246");

new DetectFaceDemo().run();

}

}

//运行结果:

//Hello, OpenCV

//

//Running DetectFaceDemo

///E:/eclipse_Jee/workspace/JavaOpenCV246/bin/com/njupt/zhb/test/lbpcascade_frontalface.xml

//Detected 8 faces

//Writing faceDetection.png
package com.njupt.zhb.test;
public class TestMain {
public static void main(String[] args) {
System.out.println("Hello, OpenCV");
// Load the native library.
System.loadLibrary("opencv_java246");
new DetectFaceDemo().run();
}
}
//运行结果:
//Hello, OpenCV
//
//Running DetectFaceDemo
///E:/eclipse_Jee/workspace/JavaOpenCV246/bin/com/njupt/zhb/test/lbpcascade_frontalface.xml
//Detected 8 faces
//Writing faceDetection.png

㈣ 人脸识别特征码有哪些信息组成

人脸的位置和大小和人脸的纹理信息。确定图像中人脸所在的位置和大小是人脸识别特族芹征码中最基本的信息,兆岩毕人脸的纹理信息包括皮肤纹理、皱纹、色斑、痣等信息。枣迅人脸识别系统要考虑光照、素质、姿态等诸多影响因素,以获得更准确的识别结果。

㈤ 人脸识别算法是指什么

教程操作环境:windows7系统、Dell G3电脑。
人脸识别(Facial Recognition),就是通过视频采集设备获取用户的面部图像,再利用核心的算法对其脸部的五官位置、脸型和角度进行计算分析,进而和自身数据库里已有的范本进行比对,后判断出用户的真实身份。
人脸识别算法是指在检测到人脸并定位面部关键特征点之后,主要的人脸区域就可以被裁剪出来,经过预处理之后,馈入后端的识别算法。识别算法要完成人脸特征的提取,并与库存的已知人脸进行比对,完成最终的分类。
人脸识别的算法有 4 种:基于人脸特征点的识别算法、基于整幅 人脸图像的识别算法、基于模板的识别算法、利用神经网络进行识别的算法。

人脸识别算法的原理:
系统输入一般是一张或者一系列含有未确定身份的人脸图像,以及人脸数据库中的若干已知身份的人脸图象或者相应的编码,而其输出则是一系列相似度得分,表明待识别的人脸的身份。
人脸识别的三个经典算法
1、Eigenfaces(特征脸)算法

Eigenfaces是在人脸识别的计算机视觉问题中使用的一组特征向量的名余滑举称,竖碧Eigenfaces是基于PCA(主成分分析)的,所以学习Eigenfaces需要我们了解PCA的原理。
基本思想
主成分分析(PCA)是一种矩阵的压缩算法,在减少矩阵维数的同时尽可能的保留原矩阵的信息,简单来说就是将 n×m的矩阵转换成n×k的矩阵,仅保留矩阵中所存在的主要特性,从而可以大大节省空间和数据量。PCA的实现需要进行降维,也就是将矩阵进行变换,从更高的维度降到低的维度,然而PCA的降维离不开协方差矩阵。方差是描述一维数据样本本身相对于均值的偏离程度,是一种用来度量两个随机变量关系的统计量,从角度来说,其夹角越小,值越大,方向越相近,也就是越正相关。协方差矩阵度量除了是两个随机变量的关系外,还是维度与维度之间的关系,而非样本与样本之间的关系。
学习一种新的东西,尤其是知识,我们需要了解知识中的思想。我在了解和学习Eigenface算法时它的思想是图像识别首先要选择一个合适的子空间,将所有的图像集中到这个子空间中,然后在这个子空间中衡量相似性或者进行分类学习,再讲子空间变换到另一个空间中,这样的作用一是同一个类别的图像离得更近,二是不同的类别的图像会离得比较远;这样经过线性分类分开的图像在新空间就能容易分开。同时特征脸技术会寻找人脸图像分布的基本元素,即人脸图像样本集协方差矩阵的特征向量,以此来表征人脸图像。人脸图像的基本元素有很多,比如眼、面颊、唇等基本元素,这些特征向量在特征脸的图像空间中对应生成的子空间被称为子脸空间。
生成了子空间之后就要进行空间构造,那么如何进行空间构造呢?首先要寻找人脸的共性,其次是要寻找个体与共性的差异,还有就是要明白共性其实是空间,个体就是向量。利用协方差矩阵把目标集中所有人脸图像的特征值进行分解,得到对应的特征向量,这些特征向量就是“特征脸”。寻找特征向量的特性,将其进行线性组合。在以每一个特征子脸为基的空间,每个人脸就是一个点,这个点的坐标就是每一个人脸在每个特征基下的的投影坐标。
Eigenfaces算法过程
获得人脸图像数据,将每一个人脸图像矩阵按行串成一维,每个人脸就是一个向量;
将M个人脸在对应维度上加起来,然后求平均得到“平均脸”;
将每个图像都减去平均脸向量;
计算协方差矩阵;
运用Eigenfaces记性人脸识别;
算法实践过程;
训练图像
求出平均脸
获得特征子脸
进行图像重构
寻找相似度高的人脸图像。
2、FisherFace算法
FisherFace是Fisher线性判别在人脸识别的应用。线性判别分析(LDA)算法思想最早由英国统计与遗传学家,现代统计科学的奠让巧基人之一罗纳德*费舍尔(Ronald)提出。LDA算法使用统计学方法,尝试找到物体间特征的一个线性组合,在降维的同时考虑类别信息。通过该算法得到的线性组合可以用来作为一个线性分类器或者实现降维。
基本思想
线性判别分析的基本思想是:将高维的模式样本投影到低维最佳矢量空间,以达到抽取重要分类信息和压缩特征空间维度的效果,投影后保证模式样本在新的子空间有最大的类间距离、最小的类内距离,即模式在该空间中有最佳的可分离性。理论和特征脸里用到的Eigenfaces有相似之处,都是对原有数据进行整体降维映射到低维空间的方法,fisherfaces和Eigenfaces都是从数据整体入手而不同于LBP提取局部纹理特征。
对降维后的样本使用Fisher线性判别方法,确定一个最优的投影方向,构造一个一维的体征空间,将多维的人脸图像投影到 fisherfaces特征空间,利用类内样本数据形成一组特征向量,这组特征向量就代表了人脸的特征。
我们知道,该算法是在样本数据映射到另外一个特征空间后,将类内距离最小化,类间距离最大化。LDA算法可以用作降维,该算法的原理和PCA算法很相似,因此LDA算法也同样可以用在人脸识别领域。通过使用PCA算法来进行人脸识别的算法称为特征脸法,而使用LDA算法进行人脸识别的算法称为费舍尔脸法。
LDA和PCA相比:
相同:1、在降维的时候,两者都使用了矩阵的特征分解思想;2、两者都假设数据符合高斯分布。不同:1、LDA是有监督的降维方法,而PCA是无监督的。2、如果说数据是k维的,那么LDA只能降到(k-1)维度,而PCA不受此限制。3、从数学角度来看,LDA选择分类性能最好的投影方向,而PCA选择样本投影点具有最大方差的方向。Fisherfaces算法和Eigenfaces算法相比:
相同:两者均可以对数据进行降维;两者在降维时均使用了矩阵特征分解的思想。
不同:Fisherfaces是有监督的降维方法,而是Eigenfaces无监督的降维方法;Fisherfaces除了可以用于降维,还可以用于分类。
值得一提的是,FisherFace算法识别的错误率低于哈佛和耶鲁人脸数据库测试的Eigenfaces识别结果。
Fisherface算法流程
获得人脸图像数据,然后求出人脸的均值。
观察各个人脸的特征值。
进行人脸鉴定,观察人脸特征,判断是否是个人。
最后进行人脸识别。
3、LBPH(Local Binary Patter Histogram)算法
Local Binary Patterns Histograms即LBP特征的统计直方图,LBPH将LBP(局部二值编码)特征与图像的空间信息结合在一起。如果直接使用LBP编码图像用于人脸识别。其实和不提取LBP特征区别不大,因此在实际的LBP应用中,一般采用LBP编码图像的统计直方图作为特征向量进行分类识别。
原始的LBP算子定义为在33的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于或等于中心像素值,则该像素点的位置被标记为1,否则为0。这样,33邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理特征。
LBPH的维度: 采样点为8个,如果用的是原始的LBP或Extended LBP特征,其LBP特征值的模式为256种,则一幅图像的LBP特征向量维度为:64256=16384维,而如果使用的UniformPatternLBP特征,其LBP值的模式为59种,其特征向量维度为:6459=3776维,可以看出,使用等价模式特征,其特征向量的维度大大减少,这意味着使用机器学习方法进行学习的时间将大大减少,而性能上没有受到很大影响。
基本思想
建立在LBPH基础上的人脸识别法基本思想如下:首先以每个像素为中心,判断与周围像素灰度值大小关系,对其进行二进制编码,从而获得整幅图像的LBP编码图像;再将LBP图像分为个区域,获取每个区域的LBP编码直方图,继而得到整幅图像的LBP编码直方图,通过比较不同人脸图像LBP编码直方图达到人脸识别的目的,其优点是不会受到光照、缩放、旋转和平移的影响。
LBPH算法“人”如其名,采用的识别方法是局部特征提取的方法,这是与前两种方法的最大区别。
LBPH 算法流程
LBP特征提取:根据上述的均匀LBP算子处理原始图像;
LBP特征匹配(计算直方图):将图像分为若干个的子区域,并在子区域内根据LBP值统计其直方图,以直方图作为其判别特征。
4、算法的复现代码
1)、EigenFaces算法
#encoding=utf-8
import numpy as np
import cv2
import os

class EigenFace(object):
def __init__(self,threshold,dimNum,dsize):
self.threshold = threshold # 阈值暂未使用
self.dimNum = dimNum
self.dsize = dsize

def loadImg(self,fileName,dsize):
‘‘‘
载入图像,灰度化处理,统一尺寸,直方图均衡化
:param fileName: 图像文件
:param dsize: 统一尺寸大小。元组形式
:return: 图像矩阵
‘‘‘
img = cv2.imread(fileName)
retImg = cv2.resize(img,dsize)
retImg = cv2.cvtColor(retImg,cv2.COLOR_RGB2GRAY)
retImg = cv2.equalizeHist(retImg)
# cv2.imshow(‘img’,retImg)
# cv2.waitKey()
return retImg

def createImgMat(self,dirName):
‘‘‘
生成图像样本矩阵,组织形式为行为属性,列为样本
:param dirName: 包含训练数据集的图像文件夹路径
:return: 样本矩阵,标签矩阵
‘‘‘
dataMat = np.zeros((10,1))
label = []
for parent,dirnames,filenames in os.walk(dirName):
# print parent
# print dirnames
# print filenames
index = 0
for dirname in dirnames:
for subParent,subDirName,subFilenames in os.walk(parent+’/’+dirname):
for filename in subFilenames:
img = self.loadImg(subParent+’/’+filename,self.dsize)
tempImg = np.reshape(img,(-1,1))
if index == 0 :
dataMat = tempImg
else:
dataMat = np.column_stack((dataMat,tempImg))
label.append(subParent+’/’+filename)
index += 1
return dataMat,label

def PCA(self,dataMat,dimNum):
‘‘‘
PCA函数,用于数据降维
:param dataMat: 样本矩阵
:param dimNum: 降维后的目标维度
:return: 降维后的样本矩阵和变换矩阵
‘‘‘
# 均值化矩阵
meanMat = np.mat(np.mean(dataMat,1)).T
print ‘平均值矩阵维度’,meanMat.shape
diffMat = dataMat-meanMat
# 求协方差矩阵,由于样本维度远远大于样本数目,所以不直接求协方差矩阵,采用下面的方法
covMat = (diffMat.T*diffMat)/float(diffMat.shape[1]) # 归一化
#covMat2 = np.cov(dataMat,bias=True)
#print ‘基本方法计算协方差矩阵为’,covMat2
print ‘协方差矩阵维度’,covMat.shape
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
print ‘特征向量维度’,eigVects.shape
print ‘特征值’,eigVals
eigVects = diffMat*eigVects
eigValInd = np.argsort(eigVals)
eigValInd = eigValInd[::-1]
eigValInd = eigValInd[:dimNum] # 取出指定个数的前n大的特征值
print ‘选取的特征值’,eigValInd
eigVects = eigVects/np.linalg.norm(eigVects,axis=0) #归一化特征向量
redEigVects = eigVects[:,eigValInd]
print ‘选取的特征向量’,redEigVects.shape
print ‘均值矩阵维度’,diffMat.shape
lowMat = redEigVects.T*diffMat
print ‘低维矩阵维度’,lowMat.shape
return lowMat,redEigVects

def compare(self,dataMat,testImg,label):
‘‘‘
比较函数,这里只是用了最简单的欧氏距离比较,还可以使用KNN等方法,如需修改修改此处即可
:param dataMat: 样本矩阵
:param testImg: 测试图像矩阵,最原始形式
:param label: 标签矩阵
:return: 与测试图片最相近的图像文件名
‘‘‘
testImg = cv2.resize(testImg,self.dsize)
testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)
testImg = np.reshape(testImg,(-1,1))
lowMat,redVects = self.PCA(dataMat,self.dimNum)
testImg = redVects.T*testImg
print ‘检测样本变换后的维度’,testImg.shape
disList = []
testVec = np.reshape(testImg,(1,-1))
for sample in lowMat.T:
disList.append(np.linalg.norm(testVec-sample))
print disList
sortIndex = np.argsort(disList)
return label[sortIndex[0]]

def predict(self,dirName,testFileName):
‘‘‘
预测函数
:param dirName: 包含训练数据集的文件夹路径
:param testFileName: 测试图像文件名
:return: 预测结果
‘‘‘
testImg = cv2.imread(testFileName)
dataMat,label = self.createImgMat(dirName)
print ‘加载图片标签’,label
ans = self.compare(dataMat,testImg,label)
return ans

if __name__ == ‘__main__’:
eigenface = EigenFace(20,50,(50,50))
print eigenface.predict(‘d:/face’,’D:/face_test/1.bmp’)2)、FisherFaces算法
#encoding=utf-8
import numpy as np
import cv2
import os

class FisherFace(object):
def __init__(self,threshold,k,dsize):
self.threshold = threshold # 阈值,暂未使用
self.k = k # 指定投影w的个数
self.dsize = dsize # 统一尺寸大小

def loadImg(self,fileName,dsize):
‘‘‘
载入图像,灰度化处理,统一尺寸,直方图均衡化
:param fileName: 图像文件名
:param dsize: 统一尺寸大小。元组形式
:return: 图像矩阵
‘‘‘
img = cv2.imread(fileName)
retImg = cv2.resize(img,dsize)
retImg = cv2.cvtColor(retImg,cv2.COLOR_RGB2GRAY)
retImg = cv2.equalizeHist(retImg)
# cv2.imshow(‘img’,retImg)
# cv2.waitKey()
return retImg

def createImgMat(self,dirName):
‘‘‘
生成图像样本矩阵,组织形式为行为属性,列为样本
:param dirName: 包含训练数据集的图像文件夹路径
:return: 包含样本矩阵的列表,标签列表
‘‘‘
dataMat = np.zeros((10,1))
label = []
dataList = []
for parent,dirnames,filenames in os.walk(dirName):
# print parent
# print dirnames
# print filenames
#index = 0
for dirname in dirnames:
for subParent,subDirName,subFilenames in os.walk(parent+’/’+dirname):
for index,filename in enumerate(subFilenames):
img = self.loadImg(subParent+’/’+filename,self.dsize)
tempImg = np.reshape(img,(-1,1))
if index == 0 :
dataMat = tempImg
else:
dataMat = np.column_stack((dataMat,tempImg))
dataList.append(dataMat)
label.append(subParent)
return dataList,label

def LDA(self,dataList,k):
‘‘‘
多分类问题的线性判别分析算法
:param dataList: 样本矩阵列表
:param k: 投影向量k的个数
:return: 变换后的矩阵列表和变换矩阵
‘‘‘
n = dataList[0].shape[0]
W = np.zeros((n,self.k))
Sw = np.zeros((n,n))
Sb = np.zeros((n,n))
u = np.zeros((n,1))
N = 0
meanList = []
sampleNum = []

for dataMat in dataList:
meanMat = np.mat(np.mean(dataMat,1)).T
meanList.append(meanMat)
sampleNum.append(dataMat.shape[1])

dataMat = dataMat-meanMat
sw = dataMat*dataMat.T
Sw += sw
print ‘Sw的维度’,Sw.shape

for index,meanMat in enumerate(meanList):
m = sampleNum[index]
u += m*meanMat
N += m
u = u/N
print ‘u的维度’,u.shape

for index,meanMat in enumerate(meanList):
m = sampleNum[index]
sb = m*(meanMat-u)*(meanMat-u).T
Sb += sb
print ‘Sb的维度’,Sb.shape

eigVals, eigVects = np.linalg.eig(np.mat(np.linalg.inv(Sw)*Sb))
eigValInd = np.argsort(eigVals)
eigValInd = eigValInd[::-1]
eigValInd = eigValInd[:k] # 取出指定个数的前k大的特征值
print ‘选取的特征值’,eigValInd.shape
eigVects = eigVects/np.linalg.norm(eigVects,axis=0) #归一化特征向量
redEigVects = eigVects[:,eigValInd]
print ‘变换矩阵维度’,redEigVects.shape

transMatList = []
for dataMat in dataList:
transMatList.append(redEigVects.T*dataMat)
return transMatList,redEigVects

def compare(self,dataList,testImg,label):
‘‘‘
比较函数,这里只是用了最简单的欧氏距离比较,还可以使用KNN等方法,如需修改修改此处即可
:param dataList: 样本矩阵列表
:param testImg: 测试图像矩阵,最原始形式
:param label: 标签矩阵
:return: 与测试图片最相近的图像文件夹,也就是类别
‘‘‘
testImg = cv2.resize(testImg,self.dsize)
testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)
testImg = np.reshape(testImg,(-1,1))
transMatList,redVects = fisherface.LDA(dataList,self.k)
testImg = redVects.T*testImg
print ‘检测样本变换后的维度’,testImg.shape
disList = []
testVec = np.reshape(testImg,(1,-1))
sumVec = np.mat(np.zeros((self.dsize[0]*self.dsize[1],1)))
for transMat in transMatList:
for sample in transMat.T:
disList.append( np.linalg.norm(testVec-sample))
print disList
sortIndex = np.argsort(disList)
return label[sortIndex[0]/9]

def predict(self,dirName,testFileName):
‘‘‘
预测函数
:param dirName: 包含训练数据集的文件夹路径
:param testFileName: 测试图像文件名
:return: 预测结果
‘‘‘
testImg = cv2.imread(testFileName)
dataMat,label = self.createImgMat(dirName)
print ‘加载图片标签’,label
ans = self.compare(dataMat,testImg,label)
return ans

if __name__==“__main__”:

fisherface = FisherFace(10,20,(20,20))
ans = fisherface.predict(‘d:/face’,’d:/face_test/8.bmp’)
print ans3)、LBPH算法
#encoding=utf-8
import numpy as np
import os
import cv2

class LBP(object):
def __init__(self,threshold,dsize,blockNum):
self.dsize = dsize # 统一尺寸大小
self.blockNum = blockNum # 分割块数目
self.threshold = threshold # 阈值,暂未使用

def loadImg(self,fileName,dsize):
‘‘‘
载入图像,灰度化处理,统一尺寸,直方图均衡化
:param fileName: 图像文件名
:param dsize: 统一尺寸大小。元组形式
:return: 图像矩阵
‘‘‘
img = cv2.imread(fileName)
retImg = cv2.resize(img,dsize)
retImg = cv2.cvtColor(retImg,cv2.COLOR_RGB2GRAY)
retImg = cv2.equalizeHist(retImg)
# cv2.imshow(‘img’,retImg)
# cv2.waitKey()
return retImg

def loadImagesList(self,dirName):
‘‘‘
加载图像矩阵列表
:param dirName:文件夹路径
:return: 包含最原始的图像矩阵的列表和标签矩阵
‘‘‘
imgList = []
label = []
for parent,dirnames,filenames in os.walk(dirName):
# print parent
# print dirnames
# print filenames
for dirname in dirnames:
for subParent,subDirName,subFilenames in os.walk(parent+’/’+dirname):
for filename in subFilenames:
img = self.loadImg(subParent+’/’+filename,self.dsize)
imgList.append(img) # 原始图像矩阵不做任何处理,直接加入列表
label.append(subParent+’/’+filename)
return imgList,label

def getHopCounter(self,num):
‘‘‘
计算二进制序列是否只变化两次
:param num: 数字
:return: 01变化次数
‘‘‘
binNum = bin(num)
binStr = str(binNum)[2:]
n = len(binStr)
if n = center)*(1扩展知识:人脸识别算法研究的难点
人脸识别算法研究已久,在背景简单的情形下,大部分算法都能很好的处理。但是,人脸识别的应用范围颇广,仅是简单图像测试,是远远不能满足现实需求的。所以人脸识别算法还是存在很多的难点。
光照
光照问题是机器视觉中的老问题,在人脸识别中的表现尤为明显,算法未能达到使用的程度。
姿态
与光照问题类似,姿态问题也是人脸识别研究中需要解决的一个技术难点。针对姿态的研究相对比较少,多数的人脸识别算法主要是针对正面,或接近正面的人脸图像,当发生俯仰或者左右侧而比较厉害的情况下,人脸识别算法的识别率也将会急剧下降。
遮挡
对于非配合情况下的人脸图像采集,遮挡问题是一个非常严重的问题,特别是在监控环境下,往往被监控对象都会带着眼镜﹑帽子等饰物,使得被采集出来的人脸图像有可能不完整,从而影响了后面的特征提取与识别,甚至会导致人脸识别算法的失效。
年龄变化
随着年龄的变化,面部外观也在变化,特别是对于青少年,这种变化更加的明显。对于不同的年龄段,人脸识别算法的识别率也不同。
图像质量
人脸图像的来源可能多种多样,由于采集设备的不同,得到的人脸图像质量也不同,特别是对于那些低分辨率﹑噪声大﹑质量差的人脸图像如何进行有效的人脸识别是个需要关注的问题。同样的,对于高分辨图像,对人脸识别算法的影响也需要进一步研究。
样本缺乏
基于统计学习的人脸识别算法是人脸识别领域中的主流算法,但是统计学习方法需要大量的培训。由于人脸图像在高维空间中的分布是一个不规则的流行分布,能得到的样本只是对人脸图像空间中的一个极小部分的采样,如何解决小样本下的统计学习问题有待进一步的研究。
大量数据
传统人脸识别算法如PCA、LDA等在小规模数据中可以很容易进行训练学习。但是对于大量数据,这些方法其训练过程难以进行,甚至有可能崩溃。
大规模人脸识别
随着人脸数据库规模的增长,人脸算法的性能将呈现下降。

㈥ 用java写人脸识别算法有哪些

Java中常见的人脸识别算法有:

㈦ 仿抖音特效相机之大眼瘦脸

本文是讲解特效相机中的大眼瘦脸的实现,完整源码可查看 AwemeLike 。
要实现瘦脸大眼,首先需要获取到人脸特征点,在本项目中使用的是Face++的人脸识别库,它可以获取到106个人脸特征点,接着再通过变形算法就可以实现了。

项目使用的瘦脸算法是参照这篇文章 在OpenGL中利用shader进行实时瘦脸大眼等脸型微调

textureCoord 表示陵耐当前要修改的尺拆春坐标, originPosition 表示圆心坐标, targetPosition 表示目标坐标, delta 用来控制变形强度。

上述shader方法可以这样理解,首先确定一个以 originPosition 为圆心、 targetPosition 和 originPosition 之间的距离为半径的圆,然后将圆内的像素朝着同一个方向移动一个偏移值,且偏移值在距离圆心越近时越大,最终将变换后的坐标返回。

如果将方法简化为这样的表达式 变换后的坐标 = 原坐标 - (目标坐标 - 圆心坐标) * 变形强度 ,也就是说,方法的作用就是要在原坐标的基础上减去一个偏移值,而 (targetPosition - originPosition) 决定了移动的方向和最大值。

式子中的 变形强度 可以这样表示:

除了项目中使用的算法,还有另外两种脸部变形算法可以使用,一个是基于 Interactive Image Warping 的局部调整算法(其原理可查看 文章 ),我们在项目中使用的算法其实可以看做是它的一个变种,都御乎可以用表达式 变换后的坐标 = 原坐标 - (目标坐标 - 圆心坐标) * 变形强度 来表示,不同之处在于 变形强度 的取值不同。;另一个是基于 Image deformation using moving least squares 的全局点位变形算法(其原理可查看 文章 )。

当我们要使用上述瘦脸算法时,只需要选取多对特征点作为 originPosition 和 targetPosition ,使得它们作用范围覆盖的两个脸颊和下巴,然后通过改变 delta 来控制瘦脸的强度。

在Face++中,获取的106个特征点分布如下

将这106个特征点上传到片元着色器

设置统一的变形强度

指定圆心坐标和目标坐标,共有9对

大眼算法也是参照这篇文章 在OpenGL中利用shader进行实时瘦脸大眼等脸型微调

textureCoord 表示当前要修改的坐标, originPosition 表示圆心坐标, radius 表示圆的半径, delta 用来控制变形强度。
和瘦脸的算法类似,根据 originPosition 和 targetPosition 确定一个圆,圆内的坐标会参与计算,圆外的不变。
圆内的坐标围绕圆心 originPosition 在变化,最终的坐标完全是由 weight 的值决定, weight 越大,最终的坐标变化越小,当 weight 为1,即坐标处于圆边界或圆外时,最终的坐标不变;当 weight 小于1时,最终的坐标会落在原坐标和圆点之间,也就是说最终返回的像素点比原像素点距离圆点更近,这样就产生了以圆点为中心的放大效果。

项目中的 FaceDetector 是一个专门用来处理Face++相关的操作的类,其头文件如下

使用前需要替换Face++的key和secret,在项目中,它的路径是 Face++/MGNetAccount.h ,然后调用授权方法,授权成功之后才能使用face++的人脸检测。

face++接受的是 CMSampleBufferRef 类型的视频帧,但他不支持YUV格式,所以在解码时需要选择BGRA格式。

项目使用 GPUImage 来做解码,但 GPUImage 库在将视频帧解码为BGRA格式时有一些实现问题,所以我们在使用相机和读取视频文件时,一定要使用项目自己创建的 GPUImageFaceCamera 和 GPUImageFaceMovie ,它们分别继承自 GPUImage 的 GPUImageVideoCamera 和 GPUImageMovie ,在内部重写了一些配置方法,使得返回的视频帧格式都是BGRA。

除此以外,这两个类在获取到视频帧之后还会自行调用 FaceDetector 的 - (void)getLandmarksFromSampleBuffer:(CMSampleBufferRef)detectSampleBufferRef; 方法获取人脸信息,使得我们可以在之后的滤镜类中直接使用它解析出来的人脸数据了。

人脸方向是指人脸在视频帧中的逆时针偏移角度,偏移角度为0表示人脸是正的,处于竖直方向。

如果给我们一张人脸的图片,我们的肉眼很容易判断出人脸在图片中的偏移角度,但是传递给face++的是一个来自相机或视频文件视频帧,那么我们应该如何获取人脸的偏移角度呢。

1. 相机拍摄( GPUImageFaceCamera )

当使用相机拍摄时,相机产生的视频帧默认情况下和我们看到的并不一样,可以通过 AVCaptureConnection 类的属性 videoOrientation 来指定视频帧的方向,其取值有如下几种

上面提到的原图就是我们肉眼看到的场景,它和相机或视频文件产生的视频帧可能是不一样的。

因为项目是通过 GPUImage 库来调用相机的,而 GPUImage 并没有设置这个属性——它使用的是默认值,所以项目使用的是这个属性的默认值。(使用默认值可能是性能原因,因为设置这个属性会导致系统应用一个相应matrix来旋转视频帧,GPUImage选择将旋转操作放到了GPU中执行)

后置摄像头

在使用后置摄像头时, videoOrientation 属性的默认值是 ,也就是说当手机水平方向放置,且home键在右边时,相机产生的图片和原图一致。
根据这个,我们可以得出下面两个变换图,左边的图片代表原图(实际场景),右边代表相机产生的视频帧,也是传递给face++的视频帧,每一行代表一个放置手机的方向。

我们需要根据上面两个图来得到人脸的偏移角度

首先我们需要设置了一个前提,人脸在原图中总是处于竖直方向的,即偏移角度为0,这其实是符合逻辑的,我们的脑袋不可能歪到大于90度。
然后我们可以将上图中的3和4看做是人脸,计算出右图中的3和4的旋转角度,就可以得出在当前手机方向下人脸的偏移角度。

最终我们得出了下面这个对照表

前置摄像头

使用前置摄像头时, videoOrientation 的默认值为 ,同样的,当手机水平方向放置进行拍摄,home键在左边时,相机产生的图片和原图是水平镜像的关系,所以还需要额外做一个水平方向的翻转,这时的图片才和原图一样。

同样给出手机处于竖直方向或水平方向拍摄时,原图和视频帧的变换

手机方向和人脸偏移角度的对照表

相比后置摄像头,使用前置摄像头时需要多做一个额外的水平翻转,由于face++并没有提供设置水平翻转的接口,所以在识别前置摄像头产生的图片时,face++返回的人脸数据有一些小问题——人脸特征点的排列顺序左右颠倒了,不过这个问题是可以忽略的,因为人脸两边是对齐的;还有一个问题就是欧拉角的方向会取反,这个我们后面会讲到怎么解决。

检测手机的方向

由于App只支持 Portrait 方向,所以无法使用类似 - (void):(UIInterfaceOrientation)toInterfaceOrientation ration:(NSTimeInterval)ration 方法来获取手机方向。
一个更好的方法是通过 CoreMotion 检测xyz方向的加速度,以此来判断当前手机的朝向

2. 从视频文件获取( GPUImageFaceMovie )

通过 AVAssetTrack 的 preferredTransform 属性获得变换矩阵,再通过矩阵来判断视频的旋转角度,也即是人脸的旋转角度。

face++返回的人脸数据会在哪里被使用?

GPUImage 会将视频帧上传到纹理中,然后将纹理传递给后续的 targets , targets 是指那些遵守了 GPUImageInput 协议的类,在这里我们简称它们为滤镜类。

face++返回的人脸数据只会被使用在这些滤镜类中,这些滤镜类中的纹理图片和传递给face++做人脸检测的视频帧是不一样的,也就是说生成人脸数据时的参考坐标系和使用人脸数据时的参考坐标系是不同的。所以在使用人脸数据之前,我们还需要对人脸数据做一些转换操作。

问题是如何转换

之前在设置人脸方向时,我们已经了解了视频帧,那么滤镜类中的纹理又是什么样的,可以参考下面这张图

第一行使用后置摄像头,第二行使用前置摄像头;
第一列和第二列分别表示原图和相机产生的视频帧;
第三列表示视频帧上传到纹理时的情形,因为OpenGL的原点是在左下角,所以需要上下颠倒;
第四列表示变换后的纹理图片,也就是滤镜类中的纹理图片。

( GPUImage 是如何从上图的第三列变换到第四列的,查看 GPUImageVideoCamera 的方法 可知,按照本项目对 GPUImageVideoCamera 的配置( outputImageOrientation=, _=true ,前置),当使用后置摄像头时,用来指定旋转的枚举是 kGPUImageRotateRight ,当使用前置摄像头时,用来指定旋转的枚举是 ,这两个枚举的名字刚好是反向变换——第四列变换到第三列所需要的步骤)

特征点坐标

假设 point 表示使用后置摄像头时Face++的特征点坐标,对应上图的第一行的视频帧,它是以4号位作为原点,也就是说 point 的值是相对于4号位的,然后我们再看第一行的最终纹理图片,原点是3号位,4号位变换到右下角了,我们需要做的是将 point 变换到以3号位为原点。

所以变换后的 point 应该等于 (height - point.y, point.x) ,其中width是第二列视频帧的4号位和2号位所在的那条边的长度,height是视频帧的4号位和3号位所在的那条边的长度。

特征点变换规则如下

欧拉角

faceinfo 的三个属性 pitch 、 yaw 、 roll 分别表示人脸在未变换的视频帧中围绕x、y、z轴的旋转角度。

㈧ 求教高手--ps问题:如何把一张人脸改成有很多的图片组成

我觉得可以肢丛棚这样。1先建立一个与脸部一样大小的选区,新建图层,填充任意色。2然后置入图片,ctrl+alt+g,那些需要在脸部显示的图片与任意填充颜色的图层建立剪贴蒙版关系。3改变图层混历则合模式,叠加之类的(视情况而定吧)。当然滤镜里面的置换也很有用,脸部的纹理都会反映在图片中。只是那个还要麻烦一点,需要单独保存,还要置入,还要更改混合模式,那个使用置换的时候最好用重复边缘像素郑旅。额,希望帮得到你。

阅读全文

与人脸纹理变换代码相关的资料

热点内容
桌面云配置文件分离 浏览:505
iphone5如何升级4g网络 浏览:5
团购是在哪个app 浏览:897
打开多个word文档图片就不能显示 浏览:855
腾讯新闻怎么切换版本 浏览:269
app安装失败用不了 浏览:326
桌面文件鼠标点开会变大变小 浏览:536
手机误删系统文件开不了机 浏览:883
微信兔子甩耳朵 浏览:998
android蓝牙传文件在哪里 浏览:354
苹果6s软解是真的吗 浏览:310
c语言代码量大 浏览:874
最新网络卫星导航如何使用 浏览:425
以下哪些文件属于图像文件 浏览:774
zycommentjs 浏览:414
确认全血细胞减少看哪些数据 浏览:265
文件有哪些要求 浏览:484
cad打开时会出现两个文件 浏览:65
什么是转基因网站 浏览:48
手柄设备有问题代码43 浏览:921

友情链接