需要源码请点赞关注收藏后评论区留言私信~~~~
对于简单的人脸识别操作,Android已经提供了专门的识别工具,名叫人脸检测器FaceDetector,部分常用方法如下
FaceDetector的findFaces方法可在指定位图中寻找人脸,找到的人脸结果放在该方法的第二个输入参数中,参数类型为人脸数组结构FaceDetector.Face[]。
下面是人脸对象的常用方法说明:
getMidPoint:获取人脸的中心点。
eyesDistance:获取人脸中心点和眼间距离。
confidence:获取人脸结果的信任度,取值区间为0到1,一般信任度达到0.3即可判作人脸。 pose:获取人脸在指定坐标轴的姿势,也就是与指定坐标轴的夹角。
运行测试App效果如下
原图片如下 用最近世界杯上非常火的球星C罗
经过系统自带的人脸检测器读取后效果如下 可以精确的圈出人脸位置
代码如下
package com.example.face;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.example.face.util.BitmapUtil;
import com.example.face.widget.FaceView;
public class DetectSystemActivity extends AppCompatActivity {
private final static String TAG = "DetectSystemActivity";
private int CHOOSE_CODE = 3; // 只在相册挑选图片的请求码
private FaceView fv_face; // 声明一个人脸视图对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detect_system);
fv_face = findViewById(R.id.fv_face);
findViewById(R.id.btn_choose).setOnClickListener(v -> {
// 创建一个内容获取动作的意图(准备跳到系统相册)
Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT);
albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); // 是否允许多选
albumIntent.setType("image/*"); // 类型为图像
startActivityForResult(albumIntent, CHOOSE_CODE); // 打开系统相册
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK && requestCode == CHOOSE_CODE) { // 从相册返回
if (intent.getData() != null) { // 从相册选择一张照片
Uri uri = intent.getData(); // 获得已选择照片的路径对象
// Android自带的人脸检测只支持RGB_565格式
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565; // 构造位图生成的参数,必须为RGB_565
// 根据指定图片的uri,获得自动缩小后的位图对象
Bitmap bitmap = BitmapUtil.getAutoZoomImage(this, uri, options);
fv_face.setImageBitmap(bitmap); // 设置人脸视图的位图对象
}
}
}
}
计算机视觉是一类智能化的工程领域,它研究怎么样让计算机模拟人类的视觉感知,通过观察采集到的图片或者视频处理画面信息获得三维场景结构,进而识别出有用的物体形态或行为事件
OpenCV主要由C/C++编写,同时提供多种程序语言接口,它是一个庞大的开源体系 它的概念结构图如下
OpenCV的初始化与加载操作包括:
(1)OpenCV初始化
(2)加载so库
(3)加载级联文件
(4)创建OpenCV的人脸检测器
Imgproc工具用于加工图像矩阵,例如转换颜色空间、添加各类部件、比较图像矩阵等等。
它的常见方法说明如下:
cvtColor:将图像矩阵从一种颜色空间转换为另一种颜色空间。
circle:在图像矩阵上画圆圈。
polylines:在图像矩阵上画多边形。
putText:在图像矩阵上画文本。
rectangle:在图像矩阵上画矩形。
compareHist:比较两个图像矩阵的直方图,并返回二者的相似程度。
位图中人脸检测步骤如下
(1)先将位图对象转为Mat结构,再将Mat结构转成灰度矩阵;
(2)调用人脸检测器的detectMultiScale方法,检测灰度矩阵得到人脸位置的矩形数组;
(3)依次遍历人脸数组,分别调用Imgproc工具的rectangle方法,往Mat结构上的每张人脸画上相框;
(4)把Mat结构转为位图对象,并显示到界面上;
运行测试App效果如下
可以看出照片居中 对于观看者更加友好 这也是OpenCV强大的体现
代码如下
package com.example.face;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.face.util.BitmapUtil;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
public class DetectOpencvActivity extends AppCompatActivity {
private final static String TAG = "DetectOpencvActivity";
private int CHOOSE_CODE = 3; // 只在相册挑选图片的请求码
private ImageView iv_face; // 声明一个图像视图对象
private CascadeClassifier mJavaDetector; // OpenCV的人脸检测器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detect_opencv);
iv_face = findViewById(R.id.iv_face);
findViewById(R.id.btn_choose).setOnClickListener(v -> {
// 创建一个内容获取动作的意图(准备跳到系统相册)
Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT);
albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); // 是否允许多选
albumIntent.setType("image/*"); // 类型为图像
startActivityForResult(albumIntent, CHOOSE_CODE); // 打开系统相册
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK && requestCode == CHOOSE_CODE) { // 从相册返回
if (intent.getData() != null) { // 从相册选择一张照片
Uri uri = intent.getData(); // 获得已选择照片的路径对象
// 根据指定图片的uri,获得自动缩小后的位图对象
Bitmap bitmap = BitmapUtil.getAutoZoomImage(this, uri);
detectFace(bitmap); // 检测位图中的人脸
}
}
}
// 检测位图中的人脸
private void detectFace(Bitmap orig) {
Mat rgba = new Mat();
Utils.bitmapToMat(orig, rgba); // 把位图对象转为Mat结构
//Mat rgba = Imgcodecs.imread(mFilePath); // 从文件路径读取Mat结构
//Imgcodecs.imwrite(tempFile.getAbsolutePath(), rgba); // 把Mate结构保存为文件
Mat gray = new Mat();
Imgproc.cvtColor(rgba, gray, Imgproc.COLOR_RGB2GRAY); // 全彩矩阵转灰度矩阵
// 下面检测并显示人脸
MatOfRect faces = new MatOfRect();
int absoluteFaceSize = 0;
int height = gray.rows();
if (Math.round(height * 0.2f) > 0) {
absoluteFaceSize = Math.round(height * 0.2f);
}
if (mJavaDetector != null) { // 检测器开始识别人脸
mJavaDetector.detectMultiScale(gray, faces, 1.1, 2, 2,
new Size(absoluteFaceSize, absoluteFaceSize), new Size());
}
Rect[] faceArray = faces.toArray();
for (Rect rect : faceArray) { // 给找到的人脸标上相框
Imgproc.rectangle(rgba, rect.tl(), rect.br(), new Scalar(0, 255, 0, 255), 3);
Log.d(TAG, rect.toString());
}
Bitmap mark = Bitmap.createBitmap(orig.getWidth(), orig.getHeight(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rgba, mark); // 把Mat结构转为位图对象
iv_face.setImageBitmap(mark);
}
@Override
protected void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
if (status == LoaderCallbackInterface.SUCCESS) {
Log.d(TAG, "OpenCV loaded successfully");
// 在OpenCV初始化完成后加载so库
System.loadLibrary("detection_based_tracker");
File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
// 从应用程序资源加载级联文件
try (InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
FileOutputStream os = new FileOutputStream(cascadeFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
}
// 根据级联文件创建OpenCV的人脸检测器
mJavaDetector = new CascadeClassifier(cascadeFile.getAbsolutePath());
if (mJavaDetector.empty()) {
Log.d(TAG, "Failed to load cascade classifier");
mJavaDetector = null;
} else {
Log.d(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath());
}
cascadeDir.delete();
} else {
super.onManagerConnected(status);
}
}
};
}
创作不易 觉得有帮助请点赞关注收藏~~~