OpenCV for Java 《一:实现从摄像头检测人脸》

网上关于 OpenCV Java 的资料特别少,记录下自己的学习过程,读取摄像头并画出框来。

环境

1
2
3
OS: macOS 10.13.3
OpenCV: 3.4.0_1
IDE: IntelliJ IDEA 2017.2.6

步骤

第一步:加载 OpenCV 的库

项目创建好后,参考前面的 OpenCV 安装里面的 “IntelliJ 使用 OpenCV”,添加启动参数和包,然后加载 OpenCV 的库如下(重要记笔记)

一定要先加载,不然会报错,这里写在主方法第一条

1
2
3
4
5
6
public static void main(String[] args) {
//加载 OpenCV 库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//省略代码
.....
}

第二步:读取摄像头

读取摄像头使用 OpenCV 的 VideoCapture 类相关方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
VideoCapture(int index)  

index :
要读取的摄像头 ID,从0开始,你电脑有2个摄像头,你要读取第2个,就写1

VideoCapture(String filename)

filename:
视频文件的名称(例如video.avi)
或图像序列(例如img_%02d.jpg,它将读取样本img_00.jpg, img_01.jpg, img_02.jpg, ...)
或视频流的URL(例如protocol://host:port/script_name?script_params|auth)。请注意,每个视频流或IP摄像头供稿都有自己的URL方案。请参阅源码流的文档以了解正确的URL。

double get(int propId)

propId:
Videoio.CV_CAP_PROP_FRAME_WIDTH (获取摄像头或图片分辨率的宽)
Videoio.CV_CAP_PROP_FRAME_HEIGHT (获取摄像头或图片分辨率的高)
Videoio.CV_CAP_PROP_FPS (获取摄像头或图片分辨率的帧率)

boolean isOpened()

判断摄像头、视频、图片序列是否读取成功

boolean read(Mat image)

读取一帧,存到image

Imgcodecs.imwrite()把 Mat 存成图片 Imgcodecs.imread() 把图片读取为 Mat

简单的读取本机的摄像头,存到桌面文件夹,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//	读取摄像头
VideoCapture capture = new VideoCapture(0);
// 检测下是否找到摄像头
if (!capture.isOpened()) {
throw new RuntimeException("无法找到摄像头,请检查是否存在摄像头设备。");
}

int i = 0;

Mat img = new Mat();
//循环读取摄像头
while (true) {
//读取一帧
capture.read(img);

//存到桌面文件夹里面
Imgcodecs.imwrite("/Users/limbang/Desktop/img/"+i+".jpg",img);
i++;

// 检测间隔
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

第三步:检测人脸

有了图片就可以测人脸了,这里使用官方训练好的模型, MAC 路径:/usr/local/Cellar/opencv/3.4.0_1/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml为检测人脸的模型,要识别的图片路径 /Users/limbang/Desktop/img/img.jpg ,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 创建分类器
CascadeClassifier face_cascade = new CascadeClassifier();
// 加载人脸检测器,我这里是直接使用原路径里面的,你可以复制的资源目录在读取
if (!face_cascade.load("/usr/local/Cellar/opencv/3.4.0_1/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml")) {
throw new RuntimeException("加载人脸检测模型失败,请检测路径");
}

Mat img = Imgcodecs.imread("/Users/limbang/Desktop/img/img.jpg");

Mat grayImg = new Mat();
// 转成灰度图像
Imgproc.cvtColor(img, grayImg, Imgproc.COLOR_RGB2GRAY);
// 直方图均衡化
Imgproc.equalizeHist(grayImg, grayImg);
// 设置人脸检测的最小尺寸为帧高度的百分之20
int height = grayImg.rows();
int absoluteFaceSize = Math.round(height * 0.2f);
// 建立用于存放人脸的向量容器
MatOfRect faces = new MatOfRect();
// 检测人脸
face_cascade.detectMultiScale(grayImg, faces,
1.1,
4,
0 | Objdetect.CASCADE_SCALE_IMAGE,
new Size(absoluteFaceSize, absoluteFaceSize),
new Size());
// 画出所有人脸
for (Rect rect : faces.toArray()) {
// 框出人脸
Imgproc.rectangle(img,
new Point(rect.x, rect.y),
new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0));
// 加上文字
Imgproc.putText(img,
"face",
new Point(rect.x, rect.y - 7),
3,
1.2,
new Scalar(0, 255, 0),
2);
}

Imgcodecs.imwrite("/Users/limbang/Desktop/img/img-1.jpg",img);

原图
opencv-face
检测后
opencv-face

注意:在摄像头连续读取并实时检测显示,使用detectMultiScale检测人脸,如果不加那个最大最小尺寸,会使 CPU 起飞,视频掉帧

官方文档 detectMultiScale 参数详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void	detectMultiScale(Mat image, MatOfRect objects) 
void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize)


Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles.

Parameters:
image Matrix of the type CV_8U containing an image where objects are detected.
objects Vector of rectangles where each rectangle contains the detected object, the rectangles may be partially outside the original image.
scaleFactor Parameter specifying how much the image size is reduced at each image scale.
minNeighbors Parameter specifying how many neighbors each candidate rectangle should have to retain it.
flags Parameter with the same meaning for an old cascade as in the function cvHaarDetectObjects. It is not used for a new cascade.
minSize Minimum possible object size. Objects smaller than that are ignored.
maxSize Maximum possible object size. Objects larger than that are ignored. If maxSize == minSize model is evaluated on single scale.

The function is parallelized with the TBB library.

---------------- The End ----------------
分享到: