Java+OpenCV 学习笔记

OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉机器学习软件库。OpenCV用C++语言编写,它具有C ++,PythonJavaMATLAB接口,实现了图像处理和计算机视觉方面的很多通用算法。

1.OpenCV 环境配置

  1. 首先在OpenCV官网下载并安装到电脑上Releases - OpenCV
  2. 配置环境变量,在 开始–搜索查看高级系统设置–环境变量 打开。在系统变量中新建变量,变量名为OPENCV_DIR,变量值为OpenCV的安装路径。然后编辑Path变量,新建xxx\opencv\build\java\x64和xxx\opencv\build\bin。
  3. 在IDEA的Project Structure中导入安装的opencv-xxx.jar和opencv_javaxxx.dll.分别在opencv\build\java和opencv\build\java\x64目录下。

2.图像读取和输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

public class GetImg {
public static void main(String[] args) {
//调用OPENCV的库文件,必须写
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//读取图片
Mat src1 = Imgcodecs.imread("E:\\lena.jpg");
//读取图片并转为灰度图像
Mat src2 = Imgcodecs.imread("E:\\lena.jpg",Imgcodecs.IMREAD_GRAYSCALE);
//展示图像
HighGui.imshow("lena",src1);
HighGui.waitKey(0);
//输出图像
Imgcodecs.imwrite("gray.jpg",src2);
System.out.println("OK!");
}
}

3.图像处理基础

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
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

public class ImageProcessing {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//读取图像
Mat red = Imgcodecs.imread("img/red.jpg");
Mat blue = Imgcodecs.imread("img/blue.jpg");
HighGui.imshow("red",red);
HighGui.waitKey(0);
HighGui.imshow("blue",blue);
HighGui.waitKey(0);

Mat image = new Mat();
//图像加权平均混合
Core.addWeighted(red,0.5,blue,0.5,0,image);
HighGui.imshow("image",image);
HighGui.waitKey(0);
//数值上的简单相加,如果大于255就为255,255即为白色
Core.add(red,blue,image);
HighGui.imshow("image",image);
HighGui.waitKey(0);
//反相
Core.bitwise_not(red,image);
HighGui.imshow("image",image);
HighGui.waitKey(0);

System.exit(0);
}
}

图像加权平均混合数值上的简单相加反相

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
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class WarpAffine {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
/** 透视变换
* 与仿射变换相似,但是点集是需要变换的图片的四个角点
* 而使用的函数是Imgproc.getPerspectiveTransform()
* 和Imgproc.warpPerspective()
*/
Mat book = Imgcodecs.imread("img/book.jpg");
Mat image = new Mat();
Point[] points1 = new Point[4];
points1[0] = new Point(100,55);
points1[1] = new Point(395,84);
points1[2] = new Point(80,388);
points1[3] = new Point(370,379);

Point[] points2 = new Point[4];
points2[0] = new Point(0,0);
points2[1] = new Point(300,0);
points2[2] = new Point(0,300);
points2[3] = new Point(300,300);

MatOfPoint2f mop1 = new MatOfPoint2f(points1);
MatOfPoint2f mop2 = new MatOfPoint2f(points2);

Mat transform = Imgproc.getPerspectiveTransform(mop1,mop2);
Imgproc.warpPerspective(book,
image,
transform,
new Size(330,330),Imgproc.INTER_NEAREST);
HighGui.imshow("原图",book);
HighGui.imshow("透视变换",image);
HighGui.waitKey(0);
System.exit(0);
}
}

4.二值化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class blur {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat book = Imgcodecs.imread("img/book.jpg");
Mat book2 = book.clone();
//将图片从RGB图转成灰图
Imgproc.cvtColor(book,book,Imgproc.COLOR_RGB2GRAY);
//阈值化 设置阈值为85
Imgproc.threshold(book,book2,85,255,Imgproc.INTER_NEAREST);
//展示结果
HighGui.imshow("book1",book);
HighGui.waitKey(0);
HighGui.imshow("book2",book2);
HighGui.waitKey(0);
System.exit(0);
}
}

5.图像平滑

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
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class blur {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
/**
* 中值滤波:去除椒盐噪声 ksize要是单数,数值越大越明显
* 高斯滤波
* 均值滤波
*/
Mat i = Imgcodecs.imread("img/i.jpg");
Mat dst = i.clone();
HighGui.imshow("原图",i);
HighGui.waitKey(0);
//中值滤波
Imgproc.medianBlur(i,dst,9);
HighGui.imshow("中值滤波",dst);
HighGui.waitKey(0);
//高斯滤波
Imgproc.GaussianBlur(i,dst,new Size(5,5),10,10);
HighGui.imshow("高斯滤波",dst);
HighGui.waitKey(0);
//均值滤波
Imgproc.blur(i,dst,new Size(8,8));
HighGui.imshow("均值滤波",dst);
HighGui.waitKey(0);
System.exit(0);
}
}

6.腐蚀和膨胀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class i {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat i = Imgcodecs.imread("img/i.jpg");
Mat dst = i.clone();
HighGui.imshow("i",i);
HighGui.waitKey(0);
//腐蚀
Imgproc.erode(i,dst,new Mat());
HighGui.imshow("腐蚀",dst);
HighGui.waitKey(0);
//膨胀
Imgproc.dilate(i,dst,new Mat());
HighGui.imshow("膨胀",dst);
HighGui.waitKey(0);
}
}

形态学操作

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
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class i {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat i = Imgcodecs.imread("img/i.jpg");
Mat dst = i.clone();
HighGui.imshow("i",i);
HighGui.waitKey(0);
/***
* Imgproc.morphologyEx(Mat src, Mat dst, int op, Mat kernel);
* 形态学操作
* Imgproc.MORPH_OPFN: 开运算,先蚀后膨胀,可以用于去除椒盐噪声
* Imgproc.MORPH_CLOSE: 闭运算: 先膨胀后腐蚀
* lmgproc.MORPH_GRADIENT: 形态学梯度,图像膨胀与腐:的差,看上去就像轮廓
* Imgproc.MORPH_TOPHAT: 进行开运算之后得的图像与原始图像的差
* lmgproc.MORPH_BLACKHAT: 进行闭运算之后行到的图像与原始图像的差
*/
Imgproc.morphologyEx(i,dst,Imgproc.MORPH_OPEN,new Mat(),new Point(),3);
Imgproc.morphologyEx(i,dst,Imgproc.MORPH_CLOSE,new Mat(),new Point(),3);
Imgproc.morphologyEx(i,dst,Imgproc.MORPH_GRADIENT,new Mat(),new Point(),1);
Imgproc.GaussianBlur(dst,dst,dst.size(),1);
Imgproc.morphologyEx(i,dst,Imgproc.MORPH_TOPHAT,new Mat(),new Point(),3);
Imgproc.morphologyEx(i,dst,Imgproc.MORPH_BLACKHAT,new Mat(),new Point(),3);
HighGui.imshow("open",dst);
HighGui.waitKey(0);
}
}

7.图像金字塔

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
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class pyr {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat boy = Imgcodecs.imread("img/boy.jpg");
Mat dst = boy.clone();
HighGui.imshow("boy",boy);
HighGui.waitKey(0);
//向下采样(缩小)
Imgproc.pyrDown(boy,dst);
HighGui.imshow("down",dst);
HighGui.waitKey(0);
//向上采样(放大)
Imgproc.pyrUp(dst,dst);
HighGui.imshow("up",dst);
HighGui.waitKey(0);
//图像相减
Imgproc.resize(dst,dst,boy.size());//把图像大小变一致
Mat mat = new Mat(boy.size(),CvType.CV_64F);
Core.subtract(dst,boy,mat);
HighGui.imshow("sub",mat);
HighGui.waitKey(0);

}
}

图像经过向下采样再向上采样后会变得模糊,此时再用它与原图相减可得到一个简略的轮廓

8.边缘检测

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
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class detectEdge {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//读入灰图像
Mat boy = Imgcodecs.imread("img/boy.jpg",Imgcodecs.IMREAD_GRAYSCALE);
HighGui.imshow("boy",boy);
HighGui.waitKey(0);
//Sobel算法
Mat Sobel = new Mat();
Imgproc.Sobel(boy,Sobel,-1,0,1);
HighGui.imshow("Sobel",Sobel);
HighGui.waitKey(0);
//Scharr算法
Mat Scharr = new Mat();
Imgproc.Scharr(boy,Scharr,-1,0,1);
HighGui.imshow("Scharr",Scharr);
HighGui.waitKey(0);
//Laplacian算法
Mat Laplacian = new Mat();
Imgproc.Laplacian(boy,Laplacian,0);
HighGui.imshow("Laplacian",Laplacian);
HighGui.waitKey(0);
//Canny算法
Mat Canny = new Mat();
Imgproc.Canny(boy,Canny,60,200);
HighGui.imshow("Canny",Canny);
HighGui.waitKey(0);
System.exit(0);
}
}

其中Canny算法是最常用的轮廓算法,效果最明显但耗时也较长

9.模板匹配

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
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class matchTemplate {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat boy = Imgcodecs.imread("img/boy.jpg");
Mat template = Imgcodecs.imread("img/face.jpg");
HighGui.imshow("boy",boy);
HighGui.waitKey(0);
HighGui.imshow("face",template);
HighGui.waitKey(0);

//结果放到result中
Mat result = new Mat();
Imgproc.matchTemplate(boy,template,result,Imgproc.TM_CCOEFF);
//Core.minMaxLoc(result)可以得到最大和最小值的位置
Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result);
//取出最大值的位置TM_CCOEFE模式用最大值,依据最大值的位置画出矩形
Point loc = minMaxLocResult.maxLoc;
Imgproc.rectangle(boy,loc,new Point(loc.x+template.cols(),
loc.y+template.rows()),
new Scalar(255,0,0));
HighGui.imshow("boy",boy);
HighGui.waitKey(0);
System.exit(0);
}
}

10.霍夫直线检测 和 霍夫圆检测

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
45
46
47
48
49
50
51
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class HoughLineDetection {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//读取图片,并转为灰图
Mat src = Imgcodecs.imread("img/road.jpg",Imgcodecs.IMREAD_GRAYSCALE);
HighGui.imshow("src",src);
HighGui.waitKey(0);
//二值化
Imgproc.threshold(src,src,180,255,Imgproc.INTER_NEAREST);
HighGui.imshow("src",src);
HighGui.waitKey(0);
//执行边缘检测
Imgproc.Canny(src,src,60,200);
HighGui.imshow("src",src);
HighGui.waitKey(0);
//执行霍夫直线检测
Mat lines = new Mat();
Imgproc.HoughLinesP(src,lines,1,Math.PI/180,50,50,10);
/**
* src:输入图像,必须是单通道灰度图像;
* lines:输出的直线参数,每行包含4个值(x1, y1, x2, y2)
表示一条直线的两个端点坐标;
* 1:距离分辨率,表示Hough空间中距离r的分辨率,一般设置为1;
* Math.PI / 180:角度分辨率,表示Hough空间中角度θ的分辨率
一般设置为Math.PI / 180,即1度;
* 50:阈值,表示Hough空间中累加器的阈值,只有高于该值的点才会被认为是直线;
* 一般可以从一开始较低的值开始,逐渐增加来寻找最佳值
* 50:最小线段长度,表示检测到的直线的最小长度;
* 10:最大线段间隔,表示检测到的直线段之间的最大允许间隔。
*/
//画出检测的直线
//lines是 n*4 矩阵,每一行都表示一个检测到的直线(x1, y1, x2, y2)
Imgproc.cvtColor(src,src,Imgproc.COLOR_GRAY2BGR);
for (int i = 0; i < lines.rows(); i++) {
double[] data = lines.get(i, 0);
Point pt1 = new Point(data[0], data[1]);
Point pt2 = new Point(data[2], data[3]);
Imgproc.line(src,pt1,pt2,new Scalar(0,0,255),3);
}
HighGui.imshow("After HoughLineDetection",src);
HighGui.waitKey(0);
}
}
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
45
46
47
48
49
50
51
52
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class HoughCircleDetection {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("img/qi.jpg");
HighGui.imshow("src",src);
HighGui.waitKey(0);
//生成一个用于检测的灰度图像,并使用高斯模糊处理
Mat gray = new Mat();
Imgproc.cvtColor(src,gray,Imgproc.COLOR_BGR2GRAY);
Imgproc.medianBlur(gray,gray,5);
//执行霍夫圆检测
Mat circles = new Mat();
Imgproc.HoughCircles(gray,circles,
Imgproc.HOUGH_GRADIENT,
1,gray.rows()/8,100,30,1,30);
/**
* edge:输入图像,必须是单通道灰度图像。
* circles:输出参数,用于存储检测到的圆形。
* Imgproc.HOUGH_GRADIENT:检测方法,此处使用基于梯度的方法检测圆形。
* dp:检测到的圆形中心之间的距离的倒数,即图像分辨率与圆形检测分辨率的比值。默认值为1。
* minDist:
检测到的圆形中心之间的最小距离。
如果距离小于此值,则两个圆形将被视为同一圆形。默认值为图像高度的1/8。
设置为图像高度的1/8是一种经验性的做法
基于对于大部分场景下圆形的直径与图像高度的比例的分析和经验
* param1:检测过程中使用的Canny边缘检测器的高阈值。默认值为200。
* param1建议从100开始往上调整
* param2:检测过程中圆形检测的阈值,即圆形边界上的投票数。默认值为100。
* param1建议从50开始往下调整
* minRadius:要检测的圆形的最小半径。默认值为0。
* maxRadius:要检测的圆形的最大半径。默认值为0。
*/
//画出检测的圆,circles是3*n矩阵,每一列对应一个检测到的圆形(x, y, r)
for(int i=0;i<circles.cols();i++){
double[] circle = circles.get(0,i);
//获取x,y,即圆心坐标
Point center = new Point(Math.round(circle[0]),Math.round(circle[1]));
int radius = (int) Math.round(circle[2]);//获取半径
Imgproc.circle(src,center,radius,new Scalar(255,0,255),3,8,0);
}
HighGui.imshow("circles",src);
HighGui.waitKey(0);
}
}

11.角点检测

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
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class CornerDetection {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

boolean useHarrisDetector = false;

Mat book = Imgcodecs.imread("img/book.jpg");
Mat gray = book.clone();
Imgproc.cvtColor(gray,gray,Imgproc.COLOR_RGB2GRAY);

//执行角点检测
MatOfPoint corners = new MatOfPoint();
Imgproc.goodFeaturesToTrack(gray,corners,500,0.1,30,
new Mat(),3,useHarrisDetector,0.04);
/**
* image:输入图像,单通道8位或浮点型图像。
* corners:输出角点的坐标,以MatOfPoint类型返回。
* maxCorners:最大角点数。
* qualityLevel:角点的最小可接受质量水平。通常设定为 0.01 ~ 0.1 之间的小数
* minDistance:角点之间的最小欧氏距离。通常设定为图像对角线长度的 1% ~ 5% 之间的小数。
* mask:可选的输入掩模。
* blockSize:计算协方差矩阵时使用的领域大小。通常设定为 3x3 或 5x5。
* useHarrisDetector:
一个布尔值,表示是否使用Harris角点检测算法。
如果为true,则使用Harris角点检测算法,
否则使用Shi-Tomasi角点检测算法。
* k:当使用Harris角点检测算法时,表示Harris角点响应函数中的自由参数。通常设定为 0.04。
*/
//画出角点位置
Point[] points = corners.toArray();
for(int i=0;i<points.length;i++){
Imgproc.circle(book,points[i],5,new Scalar(0,0,255),2);
}
HighGui.imshow("corners",book);
HighGui.waitKey(0);

System.exit(0);
}
}

12.人脸检测及其他检测

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
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

public class Face {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat src = Imgcodecs.imread("img/boy.jpg");
src = faceDetect(src);
HighGui.imshow("src",src);
HighGui.waitKey(0);
System.exit(0);
}

public static Mat faceDetect(Mat src){
//获取级联分类器
CascadeClassifier detector = new CascadeClassifier(
"C:\\Program Files\\opencv\\sources\\data" +
"\\haarcascades\\haarcascade_frontalface_alt2.xml");
//用于存放检测结果的矩阵
MatOfRect result = new MatOfRect();
//执行检测
detector.detectMultiScale(src,result);
if(result.toArray().length<=0){
System.out.println("没有检测到人脸...");
return src;
}
//框出人脸
for(Rect rect : result.toArray()){
Imgproc.rectangle(src,rect,new Scalar(0,0,255));
}
return src;
}
}

将代码中的路径换成其他的检测模型,就可以实现检测其他物体,虽然opencv里自带的模型识别效果不是很优秀

13.视频读取与处理

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
import org.opencv.core.*;
import org.opencv.highgui.HighGui;

import org.opencv.videoio.VideoCapture;

public class VideoTest {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture capture = new VideoCapture();
capture.open("video/vtest.avi");
if(!capture.isOpened()){
System.out.println("加载失败");
return;
}
Mat frame = new Mat();
while(capture.read(frame)){//读取一帧图像到frame中
HighGui.imshow("frame",frame);
HighGui.waitKey(1);
}

capture.release();//capture释放内存
System.out.println("结束");
System.exit(0);

}
}

以上是最简单的读取视频并展示到界面中,下面代码来实现读取的同时,在每一帧上执行人体识别

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

import static org.opencv.objdetect.Objdetect.CASCADE_SCALE_IMAGE;

public class VideoTest {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture capture = new VideoCapture();
capture.open("video/vtest.avi");

if(!capture.isOpened()){
System.out.println("加载失败");
return;
}

Mat frame = new Mat();
while(capture.read(frame)){//读取一帧图像到frame中
//检测人体
faceDetect(frame);
HighGui.imshow("frame",frame);
HighGui.waitKey(1);
}

capture.release();//capture释放内存
System.out.println("结束");
System.exit(0);

}

public static void faceDetect(Mat src){
//获取级联分类器
CascadeClassifier detector = new CascadeClassifier("C:\\Program Files\\opencv" +
"\\sources\\data\\haarcascades\\haarcascade_fullbody.xml");
//用于存放检测结果的矩阵
MatOfRect result = new MatOfRect();
//执行检测
detector.detectMultiScale(src,
result,
1.3,
3,
CASCADE_SCALE_IMAGE,
new Size(40,40),
new Size(130,130));
/**
* image: 输入图像。通常是灰度图像,但也可以是彩色图像。
* scaleFactor:
* 图像缩放比例。
* 用于控制目标检测器在图像金字塔的不同层次进行检测。
* 缩小比例越小,探测到目标的可能性越高,但计算时间会增加。
* minNeighbors:
* 每个目标候选矩形应保留的邻居数。
* 这个参数用来过滤掉一些不太可能是目标的矩形,一般情况下建议设置为3-5。
* flags:
* 用来控制检测器的行为。
* 可以是默认值或者组合使用
* CASCADE_SCALE_IMAGE、
* CASCADE_FIND_BIGGEST_OBJECT、
* CASCADE_DO_ROUGH_SEARCH等参数。
* minSize: 目标的最小尺寸。用来排除一些过小的目标矩形。
* maxSize: 目标的最大尺寸。用来排除一些过大的目标矩形。
*/
if(result.toArray().length<=0){
return;
}
//框出人脸
for(Rect rect : result.toArray()){
Imgproc.rectangle(src,rect,new Scalar(0,0,255));
}
}
}

14.背景差分法

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
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
import org.opencv.video.BackgroundSubtractor;
import org.opencv.video.Video;
import org.opencv.videoio.VideoCapture;

public class BackgroundSub {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
BackgroundSubtractor subtractor;
subtractor = Video.createBackgroundSubtractorMOG2();

VideoCapture capture = new VideoCapture("video/vtest.avi");
Mat frame = new Mat();
Mat fgMask = new Mat();
while(capture.read(frame)){
subtractor.apply(frame,fgMask);//fgMask为提取的前景
Imgproc.medianBlur(fgMask,fgMask,3);
HighGui.imshow("frame",frame);
HighGui.imshow("fgMask",fgMask);
HighGui.waitKey(1);
}
capture.release();
System.exit(0);
}
}

可用于检测动态物体

15.调用摄像头执行人脸识别

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
45
46
47
48
49
50
51
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.objdetect.Objdetect;
import org.opencv.videoio.VideoCapture;

public class test2 {
//初始化分类器
static CascadeClassifier faceDetector;
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 打开摄像头获取视频流,0 打开默认摄像头
VideoCapture capture = new VideoCapture(0);
Mat video = new Mat();
while(capture.read(video)){//摄像头读取到的图像存放在video中
//传入摄像头的图像进行检测
int num = faceDetect(video);
HighGui.imshow("video",video);
//获取键盘输入
int index = HighGui.waitKey(50);
//27值Esc退出键
if (index == 27 && num!=0) {
//写入人脸
Imgcodecs.imwrite("E:\\IDEA\\openCV\\face\\" + "face.png", video);
capture.release();
return;
}
}
}

public static int faceDetect(Mat video){
//设置分类器
faceDetector = new CascadeClassifier("C:\\Program Files\\opencv" +
"\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
//定义检测后的框
MatOfRect matOfRect = new MatOfRect();
//执行检测
faceDetector.detectMultiScale(video,matOfRect,1.3,3,
Objdetect.CASCADE_SCALE_IMAGE,new Size(50,50));
//检测到的数量
Rect[] rects = matOfRect.toArray();
System.out.println("检测到"+rects.length);
//画出方框
for(Rect rect:rects){
Imgproc.rectangle(video,rect,new Scalar(255,0,0),1);
}
return rects.length;
}
}