我的Java应用程序中有一个实时的JPG图像流进入另一个线程,我想不断扫描脸部,以便稍后输出运行时通过相机的所有不同脸部的列表以及有多少个看过每张脸的次数。这是我当前的代码:
void doImageProcessing() {
// Create face stuff
FKEFaceDetector faceDetector = new FKEFaceDetector(new HaarCascadeDetector());
EigenFaceRecogniser<KEDetectedFace, Person> faceRecognizer = EigenFaceRecogniser.create(512, new RotateScaleAligner(), 512, DoubleFVComparison.CORRELATION, Float.MAX_VALUE);
FaceRecognitionEngine<KEDetectedFace, Extractor<KEDetectedFace>, Person> faceEngine = FaceRecognitionEngine.create(faceDetector, faceRecognizer);
// Start loop
while (true) {
// Get next frame
byte[] imgData = nextProcessingData;
nextProcessingData = null;
// Decode image
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgData));
// Detect faces
FImage fimg = ImageUtilities.createFImage(img);
List<KEDetectedFace> faces = faceEngine.getDetector().detectFaces(fimg);
// Go through detected faces
for (KEDetectedFace face : faces) {
// Find existing person for this face
Person person = null;
try {
List<IndependentPair<KEDetectedFace, ScoredAnnotation<Person>>> rfaces = faceEngine.recogniseBest(face.getFacePatch());
ScoredAnnotation<Person> score = rfaces.get(0).getSecondObject();
if (score != null)
person = score.annotation;
} catch (Exception e) {
}
// If not found, create
if (person == null) {
// Create person
person = new Person();
System.out.println("Identified new person: " + person.getIdentifier());
// Train engine to recognize this new person
faceEngine.train(person, face.getFacePatch());
} else {
// This person has been detected before
System.out.println("Identified existing person: " + person.getIdentifier());
}
}
}
}
问题在于,即使脸部与上一帧中检测到的脸部相同,也总是将其检测为新脸。
rfaces
始终为空。它永远无法识别现有面孔。我究竟做错了什么?另外,我也不知道
EigenFaceRecognizer
创建者函数的参数应该是什么,也许这就是为什么它不识别任何东西的原因... 最佳答案
您为EigenFaceRecogniser.create()
函数提供的参数相去甚远,因此可能是造成问题的原因。以下更可能起作用:
EigenFaceRecogniser<KEDetectedFace, Person> faceRecognizer = EigenFaceRecogniser.create(20, new RotateScaleAligner(), 1, DoubleFVComparison.CORRELATION, 0.9f);
说明:
第一个参数是EigenFace算法中主成分的数量;确切的值通常是通过实验确定的,但是大约20左右就可以了。
第三个参数是用于KNN分类器的最近邻居数。 1个最近的邻居应该可以。
最终参数是分类器的距离阈值。相关性比较返回相似性度量(高值意味着更多相似性),因此给定的阈值是必须超过的下限。由于我们设置了1个最近的邻居,因此最相似的面孔和查询面孔之间的距离必须大于0.9。请注意,值0.9只是猜测;为了优化识别器的性能,您需要尝试一下。
另一个小问题-代替:
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgData));
FImage fimg = ImageUtilities.createFImage(img);
通常,最好让OpenIMAJ读取您的图像,因为它可以解决ImageIO处理某些JPEG类型的许多已知问题:
FImage fimg = ImageUtilities.readF(new ByteArrayInputStream(imgData));