├── tutorials ├── 对象检测.md ├── 截取ROI.md ├── 获取图片像素点颜色值.md ├── 颜色空间转换.md ├── yolo │ ├── 改进调优.md │ ├── 落地应用.md │ ├── yolo-lite.md │ ├── 图片数据准备.md │ ├── 安装darknet.md │ └── yolo-v3.md ├── yolo.md ├── 小程序.md ├── 边框检测.md ├── 阈值化.md ├── Grabcut.md ├── 视频处理.md ├── 环境搭建.md ├── 直方图.md ├── DNN.md ├── OpenCV常用类和函数.md └── ml.md └── README.md /tutorials/对象检测.md: -------------------------------------------------------------------------------- 1 | #对象检测 2 | 3 | -------------------------------------------------------------------------------- /tutorials/截取ROI.md: -------------------------------------------------------------------------------- 1 | #截取ROI 2 | 3 | 样例: 4 | ``` 5 | Rect roi = new Rect(); 6 | //设置ROI 7 | Mat imgROI = new Mat(frame, roi); 8 | //目标Mat 9 | Mat imgDesc = new Mat(5, 5, CvType.CV_8UC3); 10 | //从ROI中剪切图片 11 | imgROI.copyTo(imgDesc); 12 | ``` -------------------------------------------------------------------------------- /tutorials/获取图片像素点颜色值.md: -------------------------------------------------------------------------------- 1 | # 获取图片像素点颜色值 2 | 3 | 样例: 4 | ``` 5 | Mat frame = Imgcodecs.imread(filePath); 6 | double[] midPrgb0 = frame.get((int)point.y,(int)point.x); 7 | System.out.println("原始颜色值:"+ midPrgb0[2]+","+ midPrgb0[1]+ ","+ midPrgb0[0]); 8 | ``` 9 | 10 | * 注意像素点的x,y坐标 11 | * 注意rgb空间的顺序 -------------------------------------------------------------------------------- /tutorials/颜色空间转换.md: -------------------------------------------------------------------------------- 1 | #颜色空间转换 2 | 3 | 样例: 4 | ``` 5 | Mat srcImg = Imgcodecs.imread("2.jpg"); 6 | Mat image = new Mat(); 7 | if (srcImg.empty()){ 8 | System.out.println("图片不存在"); 9 | return; 10 | } 11 | // 转为 hsv 空间 12 | Imgproc.cvtColor(srcImg,image,Imgproc.COLOR_BGR2HSV); 13 | ``` -------------------------------------------------------------------------------- /tutorials/yolo/改进调优.md: -------------------------------------------------------------------------------- 1 | # yolo改进调优 2 | 3 | 一些提高目标检测准确率的技巧 4 | 5 | 1. 更改配置文件中的配置项:random=1; 6 | 2. 增加网络输入层:设置 height=608, width=608,或者任何32的倍数,如果内存不够,增加 subdivisions 值; 7 | 3. 数据增强,对于同一张图片,可以缩放,旋转,调整亮度,调整角度,改变背景等等; 8 | 4. 添加负样本,对应标记文件置空即可; 9 | 5. 更改配置文件中的配置项:angle=90,随机旋转图片; 10 | 6. 如果需要区分左右目标为不同的分类,更改配置项:flip=0; 11 | 12 | -------------------------------------------------------------------------------- /tutorials/yolo.md: -------------------------------------------------------------------------------- 1 | # yolo系列教程 2 | 3 | yolo使用教程 4 | 5 | 1. [训练样本数据准备](/tutorials/yolo/图片数据准备.md) 6 | 2. [安装darknet](/tutorials/yolo/安装darknet.md) 7 | 3. [训练样本数据(yolo-v3)](/tutorials/yolo/yolo-v3.md) 8 | 4. [使用yolo-lite](/tutorials/yolo/yolo-lite.md) 9 | 5. [改进调优](/tutorials/yolo/改进调优.md) 10 | 6. [落地应用](/tutorials/yolo/落地应用.md) 11 | -------------------------------------------------------------------------------- /tutorials/yolo/落地应用.md: -------------------------------------------------------------------------------- 1 | # 落地应用 2 | 本文介绍训练完神经网络后,在实际应用小程序“AI看舌”中的使用。欢迎大家分享给有需要的人 3 | 4 | 1. 准备配置文件和权重文件,具体教程参考前面的教程。更改配置文件为test模式,准备map值最高的权重文件。上传到服务器。 5 | 2. 服务器安装OpenCV,centos需要注意设置 OpenCV 的系统库环境变量 6 | 3. 新建SpringBoot项目,导入本地OpenCV包,查看之前的教程,通过Java调用OpenCV的DNN模块加载权重文件和配置文件,给出预测; 7 | 4. 打包SpringBoot,上传到服务器,通过Java -jar 方式运行,也可以打包成docker镜像,然后上传到镜像服务器,通过docker运行。 8 | -------------------------------------------------------------------------------- /tutorials/yolo/yolo-lite.md: -------------------------------------------------------------------------------- 1 | # 精简版yolo 2 | 3 | 目前目标检测神经网络都不适用于互联网应用,GPU服务器价格昂贵,因此需要一个可以在CPU服务器上运行的神经网络。 4 | 5 | ## 使用步骤 6 | 1. 下载配置文件:https://github.com/reu2018DL/YOLO-LITE/blob/master/cfg/tiny-yolov2-trial13-noBatch.cfg 7 | 2. 更改配置文件中的classes、convolutional的 filters 参数,注意: 8 | * yolo-lite基于yolo-v2,convolutional filters 参数设置为(classes + 5)x5 9 | 3. 其他步骤和训练yolo-v3的数据都是一样; 10 | -------------------------------------------------------------------------------- /tutorials/小程序.md: -------------------------------------------------------------------------------- 1 | # 小程序系列教程 2 | 需要和后台接口配合,后台采用PHP,Java均可,本教程两者均有涉及。 3 | 4 | 1. [开发环境搭建](/tutorials/小程序/开发环境搭建.md)【完善中】 5 | 2. [开发框架准备](/tutorials/小程序/框架准备.md)【完善中】 6 | 3. [登录](/tutorials/小程序/登录.md)【完善中】 7 | 4. [websocket](/tutorials/小程序/websocket.md)【完善中】 8 | 5. [语音识别](/tutorials/小程序/语音识别.md)【完善中】 9 | 6. [视频直播](/tutorials/小程序/视频直播.md)【完善中】 10 | 7. [微信支付](/tutorials/小程序/微信支付.md)【完善中】 -------------------------------------------------------------------------------- /tutorials/边框检测.md: -------------------------------------------------------------------------------- 1 | #查找轮廓 2 | 3 | ## 样例: 4 | ``` 5 | Mat result = new Mat(rect.size(),CvType.CV_8U); 6 | // 查找轮廓 7 | List contours = new ArrayList<>(); 8 | 9 | Mat hierarchy = new Mat(); 10 | //RETR_EXTERNAL 只检测出最外轮廓。第一个轮廓指向最外的序列,除此之外没有别的连接。 11 | Imgproc.findContours(result, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); 12 | 13 | ``` -------------------------------------------------------------------------------- /tutorials/阈值化.md: -------------------------------------------------------------------------------- 1 | #阈值化 2 | 3 | 样例: 4 | ``` 5 | Mat image = new Mat(); 6 | if (srcImg.empty()){ 7 | System.out.println("图片不存在"); 8 | return; 9 | } 10 | 11 | // 转为 hsv 空间 12 | Imgproc.cvtColor(srcImg,image,Imgproc.COLOR_BGR2HSV); 13 | // 得到阈值化结果 14 | Imgproc.adaptiveThreshold(image,image,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY_INV,25,10); 15 | ``` -------------------------------------------------------------------------------- /tutorials/Grabcut.md: -------------------------------------------------------------------------------- 1 | #图割操作 2 | 3 | 分离指定区域的前景和背景图片 4 | 5 | ## 样例: 6 | ``` 7 | Rect rect = new Rect(point1,point2); 8 | Mat frame = Imgcodecs.imread("2.jpg"); 9 | //Grabcut分割前景与背景 10 | Mat fgMat = new Mat(), bgMat = new Mat();//定义前景与背景 11 | //定义迭代次数 12 | int i = 5; 13 | Mat result = new Mat(rect.size(),CvType.CV_8U); 14 | //实现图割操作 结果是一个二值图像 15 | Imgproc.grabCut(frame, result, rect, bgMat, fgMat, i, Imgproc.GC_INIT_WITH_RECT); 16 | 17 | //图像匹配 18 | Core.compare(result, new Scalar(3), result, Core.CMP_EQ);//比较result的值可能是前景才输出到result中 19 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpingBoot、OpenCV、yolo开发人工智能小程序经验分享 2 | 本项目分享使用SpingBoot、OpenCV、yolo的开发经验,网上很多教程都是使用C++和Python,这里选择Java语言的原因是:适合在web中集成OpenCV,C++开发门槛较高,Python性能欠佳,所以折中考虑选择Java。网站:[AI看舌](https://www.aikanshe.com/) 3 | 4 | AI看舌公众号已经上线,其中会分享我十年来的全栈架构经验,敬请关注。欢迎对中医舌诊感兴趣的机器视觉工程师加入我们团队。 5 | ![扫码关注](https://www.aikanshe.com/img/follow.jpg) 6 | 7 | # 目录 8 | 1. [环境搭建](/tutorials/环境搭建.md) 9 | 2. [OpenCV常用类和函数](/tutorials/OpenCV常用类和函数.md) 10 | 3. [获取图片像素点颜色值](/tutorials/获取图片像素点颜色值.md) 11 | 4. [颜色空间转换](/tutorials/颜色空间转换.md) 12 | 5. [直方图](/tutorials/直方图.md) 13 | 6. [边框检测](/tutorials/边框检测.md) 14 | 7. [神经网络](/tutorials/DNN.md) 15 | 8. [机器学习](/tutorials/ml.md) 16 | 9. [视频处理](/tutorials/视频处理.md) 17 | 10. [Grabcut](/tutorials/Grabcut.md) 18 | 11. [截取ROI](/tutorials/截取ROI.md) 19 | 12. [阈值化](/tutorials/阈值化.md) 20 | -------------------------------------------------------------------------------- /tutorials/视频处理.md: -------------------------------------------------------------------------------- 1 | #视频处理 2 | 3 | ## 样例: 4 | 5 | ``` 6 | // 打开摄像头或者视频文件 7 | VideoCapture capture = new VideoCapture(); 8 | //capture.open(0); 9 | capture.open("D:/vcprojects/images/768x576.avi"); 10 | if(!capture.isOpened()) { 11 | System.out.println("could not load video data..."); 12 | return; 13 | } 14 | int frame_width = (int)capture.get(3); 15 | int frame_height = (int)capture.get(4); 16 | 17 | Mat frame = new Mat(); 18 | while(true) { 19 | boolean have = capture.read(frame); 20 | Core.flip(frame, frame, 1);// Win上摄像头 21 | if(!have) break; 22 | if(!frame.empty()) { 23 | ... 24 | } 25 | try { 26 | Thread.sleep(100); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /tutorials/yolo/图片数据准备.md: -------------------------------------------------------------------------------- 1 | # 样本训练数据准备 2 | 以识别人脸图片为例 3 | 4 | ## 下载人脸图片数据集 5 | 谷歌或者百度即可 6 | 7 | ## 标注图片 8 | 9 | ### 安装yolo-mark 10 | 11 | GitHub地址:https://github.com/AlexeyAB/Yolo_mark.git 12 | 1. 安装MSVS2015 13 | 2. 下载OpenCV 4.x windows安装包,官网有下载,下载完后解压到指定目录,如:e:\opencv; 14 | 3. 导出yolo-mark源码,用 vs 打开 yolo_mark.sln,更改工程中的OpenCV的路径为本机安装路径: 15 | * 右击项目 =》属性 =》 C/C++ =》通用 =》附加目录 =》 添加一行: e:\opencv\opencv\build\include 16 | * 右击项目 =》属性 =》 链接器 =》通用 =》附加目录 =》 添加一行: e:\opencv\opencv\build\x64\vc14\lib 17 | 4. 选择编译环境为 x64 & Release,然后右击项目 =》 生成 x64/Release/yolo_mark.cmd; 18 | 5. 复制训练样本图片到 x64/Release/data/img; 19 | 6. 打开 x64/Release/data/obj.data,更改classes= 1,表示只有一个类型,根据实际情况更改; 20 | 7. 打开 x64/Release/data/obj.names,清空文件,输入face,多个的话一行一个; 21 | 8. 双击 x64/Release/yolo_mark.cmd,运行即可标注。 22 | 23 | ### 标注说明 24 | 25 | 1. 标注的框只需要包含目标对象即可 26 | 2. 如果提示确实dll文件,从OpenCV安装目录opencv\build\bin复制对应的文件到 x64/Release/ 目录下即可 27 | 3. 按数字键选择对应的类型(从0开始)后再标注 -------------------------------------------------------------------------------- /tutorials/yolo/安装darknet.md: -------------------------------------------------------------------------------- 1 | # 安装DarkNet 2 | 3 | 本教程安装的不是官网的darknet,而是分支:https://github.com/AlexeyAB/darknet.git 4 | 本教程中使用的显卡支持CUDA,如果显卡不支持CUDA,需要做点小修改,参考:https://github.com/AlexeyAB/darknet#how-to-compile-on-windows-legacy-way 5 | 6 | ## 安装步骤 7 | 8 | 1. 安装MSVS2015 9 | 2. 下载OpenCV 3.x windows安装包,官网有下载,下载完后解压到指定目录,如:e:\opencv; 10 | 3. 安装 CUDA 10.0:https://developer.nvidia.com/cuda-toolkit-archive 11 | 4. 安装 cuDNN 7.4.1:https://developer.nvidia.com/rdp/cudnn-archive 12 | 13 | 5. 导出项目,用vs打开 darknet.sln,设置编译环境为:x64 and Release, 14 | 更改工程中的OpenCV的路径为本机安装路径: 15 | * 右击项目 =》属性 =》 C/C++ =》通用 =》附加目录 =》 添加一行: e:\opencv\opencv\build\include 16 | * 右击项目 =》属性 =》 链接器 =》通用 =》附加目录 =》 添加一行: e:\opencv\opencv\build\x64\vc14\lib 17 | * 然后右击项目 =》 生成即可生成 darknet.exe 18 | 6. 复制 OpenCV 安装目录下的,opencv_world3xx.dll,opencv_ffmpeg3xx_64.dll,到darknet.exe同级目录下 19 | 20 | ## 注意事项 21 | 22 | 1. 编写此文档的时候还不支持OpenCV 4.x,如果最新版已经发布,也不建议安装OpenCV 4.x,因为后续的标注工具暂不支持; 23 | 2. 建议在支持 CUDA 的电脑上安装,否则即使一个很小的神经网络,训练会非常慢。 24 | 25 | -------------------------------------------------------------------------------- /tutorials/yolo/yolo-v3.md: -------------------------------------------------------------------------------- 1 | # 训练样本数据 2 | 3 | DNN网络采用yolo-v3,和v2版本相比,增加了网络的层级,支持检测小目标。 4 | 5 | ## 训练步骤 6 | 7 | 1. 收集目标图片,可以从百度图片下载,建议使用爬虫,PHP语言推荐使用php-spider,Python语言有很多开源爬虫框架; 8 | 2. 安装Yolo_mark,github地址:https://github.com/AlexeyAB/Yolo_mark ,上面介绍的比较详细,需要注意以下几点: 9 | * 只支持OpenCV 2.x and OpenCV 3.x,OpenCV安装参考之前的教程; 10 | * 编译完成后,运行x64/Release/yolo_mark.cmd,如果提示缺失opencv_ffmpeg3xx_64.dll,复制OpenCV 安装目录下的opencv_ffmpeg3xx_64.dll,到yolo_mark.cmd同级目录下 11 | 12 | 3. 标注图片,参考教程:https://blog.csdn.net/qq_33485434/article/details/80597381 ; 13 | 4. 训练网络:复制x64/Release/data目录下的所有文件到darknet安装目录对应的data目录下,更改cfg/yolov3.cfg中的classes参数,和对应的卷积层参数,具体参考:https://github.com/AlexeyAB/darknet#how-to-train-to-detect-your-custom-objects 14 | 5. 常用命令: 15 | * 训练命令:darknet.exe detector train data/obj.data cfg/yolov3.cfg /backup/yolov3.weights -map 16 | 如果没有权重文件,可以省略,会随机生成一个权重文件。 17 | * 测试命令:darknet.exe detector test data/obj.data cfg/yolov3.cfg yolov3_final.weights,yolov3_final.weights为结束训练后的权重文件 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tutorials/环境搭建.md: -------------------------------------------------------------------------------- 1 | # 环境搭建 2 | window下搭建springboot 和 OpenCV 3 | 4 | ## springboot 5 | 6 | * 通过IntelliJ IDEA 创建Spring Boot操作步骤如下: 7 | 在File菜单里面选择 New > Project,然后选择Spring Initializr,接着一步步操作即可。 8 | 不懂springboot的可以参考:[Spring Boot干货系列](http://tengj.top/2017/02/26/springboot1/) 9 | 10 | ## 搭建OpenCV 11 | 进入官网,下载最新版window安装包,运行exe文件,解压到指定目录即可,比如 E:/opencv 12 | 13 | 14 | ## 整合springboot、OpenCV 15 | * 复制安装目录下的jar包到springboot resource目录下的lib目录。 16 | * 在springboot pom.xml文件中添加依赖【也可以自己建maven仓库】: 17 | ``` 18 | 19 | org.opencv 20 | opencv 21 | 4.1.0 22 | system 23 | ${project.basedir}/src/main/resources/lib/opencv-410.jar 24 | 25 | ``` 26 | * 引入OpenCV需要的库文件 27 | 在idea 项目的VM 参数 填写 -Djava.library.path=E:/opencv/share/lib/【window下为.dll文件,Linux下为.so文件】 28 | 29 | * 在SpringBoot启动类加载OpenCV库 30 | ``` 31 | System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 32 | SpringApplication.run(BootshiroApplication.class, args); 33 | 34 | ``` 35 | 36 | ## 注意事项 37 | * SpringBoot正式环境下不能使用javax.swing类库,开发的时候可以使用; 38 | * Linux环境下需要设置 LD_LIBRARY_PATH 环境变量:export LD_LIBRARY_PATH=/home/opencv/share/lib:$LD_LIBRARY_PATH ; 39 | -------------------------------------------------------------------------------- /tutorials/直方图.md: -------------------------------------------------------------------------------- 1 | #直方图 2 | 3 | ## 样例: 4 | ``` 5 | Mat frame = Imgcodecs.imread(filePath); 6 | // 获取H通道直方图 7 | MatOfFloat ranges = new MatOfFloat(0, 255); 8 | MatOfInt histSize = new MatOfInt(50); 9 | MatOfInt channels = new MatOfInt(1); 10 | Mat histImg = new Mat(); 11 | List mv2 = new ArrayList(); 12 | mv2.add(frame.get(0)); 13 | Imgproc.calcHist(mv2, channels, new Mat(), histImg, histSize,ranges); 14 | ``` 15 | 16 | ## 获取直方图的最小二乘解 17 | 18 | ``` 19 | public static Mat polynomial_curve_fit(Mat image,int n) { 20 | int N = image.rows(); 21 | Mat X = new Mat(n + 1, n + 1,image.type()); 22 | for (int i = 0; i < n + 1; i++) 23 | { 24 | for (int j = 0; j < n + 1; j++) 25 | { 26 | for (int k = 0; k < N; k++) 27 | { 28 | 29 | X.put(i,j,X.get(i,j)[0] + Math.pow(image.get(k,0)[0] ,i+j)); 30 | 31 | } 32 | } 33 | } 34 | 35 | //构造矩阵Y 36 | Mat Y = Mat.zeros(n + 1, 1, image.type()); 37 | for (int i = 0; i < n + 1; i++) 38 | { 39 | for (int k = 0; k < N; k++) 40 | { 41 | Y.put(i,0,Y.get(i,0)[0] + Math.pow(image.get(k,0)[0] ,i) * image.get(k,0)[1]); 42 | 43 | } 44 | } 45 | 46 | Mat A = Mat.zeros(n + 1, 1, image.type()); 47 | //求解矩阵A 48 | Core.solve(X, Y, A, Core.DECOMP_LU); 49 | 50 | return A; 51 | } 52 | ``` -------------------------------------------------------------------------------- /tutorials/DNN.md: -------------------------------------------------------------------------------- 1 | # 神经网络 2 | 3 | ## 样例: 4 | 5 | ``` 6 | Net net = Dnn.readNetFromDarknet(cfgFile, weights); 7 | 8 | Size sz = new Size(416,416); 9 | 10 | float scale = 1.0F / 255.0F; 11 | Mat inputBlob = Dnn.blobFromImage(frame, scale, sz, new Scalar(0), false, false); //Convert Mat to batch of images 12 | net.setInput(inputBlob); 13 | 14 | List outs = new ArrayList(); 15 | List outNames = net.getUnconnectedOutLayersNames(); 16 | net.forward(outs,outNames); 17 | MatOfInt outLayers = net.getUnconnectedOutLayers(); 18 | int[] layer = new int[1]; 19 | outLayers.get(0,0,layer); 20 | int layerid = layer[0]; 21 | String outLayerType = net.getLayer(new DictValue(layerid)).get_type(); 22 | 23 | List coatingpointColor = new ArrayList(); 24 | Rect rect = new Rect(); 25 | 26 | if(outLayerType.equals("Region")){ 27 | for (int i = 0; i < outs.size(); i++) { 28 | Mat detectionMat = outs.get(i); 29 | for (int r = 0; r < detectionMat.rows(); r++) 30 | { 31 | int probability_index = 5; 32 | int size = (int) (detectionMat.cols() * detectionMat.channels()); 33 | 34 | float[] data = new float[size]; 35 | detectionMat.get(r, 0, data); 36 | 37 | float confidence = -1; 38 | for (int j=0; j < detectionMat.cols();j++) 39 | { 40 | if (j >= probability_index && confidence < data[j] ) 41 | { 42 | confidence = data[j]; 43 | } 44 | } 45 | System.out.println("confidence: " + confidence); 46 | 47 | } 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /tutorials/OpenCV常用类和函数.md: -------------------------------------------------------------------------------- 1 | # OpenCV常用类和函数 2 | 3 | ## 读写图片 4 | ``` 5 | 读取指定文件路径内容:Imgcodecs.imread(filePath); 6 | 读取MultipartFile文件内容:Imgcodecs.imdecode(new MatOfByte(file.getBytes()), Imgcodecs.IMREAD_UNCHANGED); 7 | 保存图片:Imgcodecs.imwrite(filename, image); 8 | 9 | 读取视频: 10 | // 打开摄像头或者视频文件 11 | VideoCapture capture = new VideoCapture(); 12 | //capture.open(0); 13 | capture.open("D:/vcprojects/images/768x576.avi"); 14 | Mat frame = new Mat(); 15 | while(true) { 16 | boolean have = capture.read(frame); 17 | ... 18 | } 19 | 20 | 显示图片: 21 | HighGui.imshow("H",frame); 22 | HighGui.waitKey(0); 23 | 24 | ``` 25 | ## 颜色空间转换 26 | ``` 27 | Imgproc.cvtColor(srcImg,image,Imgproc.COLOR_BGR2HSV); 28 | ``` 29 | 30 | ## 直方图 31 | ``` 32 | Imgproc.calcHist(mv2, channels, new Mat(), histImg, histSize,ranges); 33 | ``` 34 | 35 | ## 求解矩阵最小二乘解 36 | ``` 37 | Core.solve(X, Y, A, Core.DECOMP_LU); 38 | ``` 39 | 40 | ## 阈值化 41 | ``` 42 | Imgproc.adaptiveThreshold(image,image,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY_INV,25,10); 43 | 44 | ``` 45 | 46 | ## 画矩形,圆形 47 | ``` 48 | Imgproc.rectangle(frame, rect,new Scalar(0, 255, 0),1); 49 | Imgproc.circle(frame,point,2,new Scalar(255,0,0),2); 50 | ``` 51 | 52 | ## 计算均值 53 | ``` 54 | Scalar scalar = Core.mean(imgDesc); 55 | ``` 56 | 57 | ## 截取ROI 58 | ``` 59 | imgROI.copyTo(imgDesc); 60 | ``` 61 | 62 | ## 获取某个像素点的颜色值(rgb空间) 63 | ``` 64 | double[] midPrgb0 = frame.get(y,x); 65 | ``` 66 | 67 | 68 | ## 查找轮廓 69 | ``` 70 | Imgproc.findContours(result, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); 71 | 72 | ``` 73 | 74 | 75 | ## 图割操作 76 | ``` 77 | //实现图割操作 结果是一个二值图像 78 | Imgproc.grabCut(frame, result, rect, bgMat, fgMat, i, Imgproc.GC_INIT_WITH_RECT); 79 | 80 | ``` 81 | 82 | ## 神经网络【yolo】 83 | ``` 84 | Net net = Dnn.readNetFromDarknet(cfgFile, weights); 85 | 86 | Mat inputBlob = Dnn.blobFromImage(frame, scale, sz, new Scalar(0), false, false); //Convert Mat to batch of images 87 | net.setInput(inputBlob); 88 | 89 | List outNames = net.getUnconnectedOutLayersNames(); 90 | net.forward(outs,outNames); 91 | MatOfInt outLayers = net.getUnconnectedOutLayers(); 92 | 93 | String outLayerType = net.getLayer(new DictValue(layerid)).get_type(); 94 | Mat detectionMat = outs.get(i); 95 | 96 | ``` 97 | -------------------------------------------------------------------------------- /tutorials/ml.md: -------------------------------------------------------------------------------- 1 | #机器学习 2 | 3 | ## // 人工神经网络 4 | ``` 5 | public static Mat MyAnn(Mat trainingData, Mat labels, Mat testData) { 6 | // train data using aNN 7 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 8 | Mat layerSizes = new Mat(1, 4, CvType.CV_32FC1); 9 | // 含有两个隐含层的网络结构,输入、输出层各两个节点,每个隐含层含两个节点 10 | layerSizes.put(0, 0, new float[] { 2, 2, 2, 2 }); 11 | ANN_MLP ann = ANN_MLP.create(); 12 | ann.setLayerSizes(layerSizes); 13 | ann.setTrainMethod(ANN_MLP.BACKPROP); 14 | ann.setBackpropWeightScale(0.1); 15 | ann.setBackpropMomentumScale(0.1); 16 | ann.setActivationFunction(ANN_MLP.SIGMOID_SYM, 1, 1); 17 | ann.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER + TermCriteria.EPS, 300, 0.0)); 18 | boolean success = ann.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 19 | System.out.println("Ann training result: " + success); 20 | // ann.save("D:/bp.xml");//存储模型 21 | // ann.load("D:/bp.xml");//读取模型 22 | 23 | // 测试数据 24 | Mat responseMat = new Mat(); 25 | ann.predict(testData, responseMat, 0); 26 | System.out.println("Ann responseMat:\n" + responseMat.dump()); 27 | for (int i = 0; i < responseMat.size().height; i++) { 28 | if (responseMat.get(i, 0)[0] + responseMat.get(i, i)[0] >= 1) 29 | System.out.println("Girl\n"); 30 | if (responseMat.get(i, 0)[0] + responseMat.get(i, i)[0] < 1) 31 | System.out.println("Boy\n"); 32 | } 33 | return responseMat; 34 | } 35 | ``` 36 | ## // Boost 37 | ``` 38 | public static Mat MyBoost(Mat trainingData, Mat labels, Mat testData) { 39 | Boost boost = Boost.create(); 40 | // boost.setBoostType(Boost.DISCRETE); 41 | boost.setBoostType(Boost.GENTLE); 42 | boost.setWeakCount(2); 43 | boost.setWeightTrimRate(0.95); 44 | boost.setMaxDepth(2); 45 | boost.setUseSurrogates(false); 46 | boost.setPriors(new Mat()); 47 | 48 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 49 | boolean success = boost.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 50 | System.out.println("Boost training result: " + success); 51 | // boost.save("D:/bp.xml");//存储模型 52 | 53 | Mat responseMat = new Mat(); 54 | float response = boost.predict(testData, responseMat, 0); 55 | System.out.println("Boost responseMat:\n" + responseMat.dump()); 56 | for (int i = 0; i < responseMat.height(); i++) { 57 | if (responseMat.get(i, 0)[0] == 0) 58 | System.out.println("Boy\n"); 59 | if (responseMat.get(i, 0)[0] == 1) 60 | System.out.println("Girl\n"); 61 | } 62 | return responseMat; 63 | } 64 | ``` 65 | ## // 决策树 66 | ``` 67 | public static Mat MyDtrees(Mat trainingData, Mat labels, Mat testData) { 68 | DTrees dtree = DTrees.create(); // 创建分类器 69 | dtree.setMaxDepth(8); // 设置最大深度 70 | dtree.setMinSampleCount(2); 71 | dtree.setUseSurrogates(false); 72 | dtree.setCVFolds(0); // 交叉验证 73 | dtree.setUse1SERule(false); 74 | dtree.setTruncatePrunedTree(false); 75 | 76 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 77 | boolean success = dtree.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 78 | System.out.println("Dtrees training result: " + success); 79 | // dtree.save("D:/bp.xml");//存储模型 80 | 81 | Mat responseMat = new Mat(); 82 | float response = dtree.predict(testData, responseMat, 0); 83 | System.out.println("Dtrees responseMat:\n" + responseMat.dump()); 84 | for (int i = 0; i < responseMat.height(); i++) { 85 | if (responseMat.get(i, 0)[0] == 0) 86 | System.out.println("Boy\n"); 87 | if (responseMat.get(i, 0)[0] == 1) 88 | System.out.println("Girl\n"); 89 | } 90 | return responseMat; 91 | } 92 | ``` 93 | ## // K最邻近 94 | ``` 95 | public static Mat MyKnn(Mat trainingData, Mat labels, Mat testData) { 96 | final int K = 2; 97 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 98 | KNearest knn = KNearest.create(); 99 | boolean success = knn.train(trainingData, Ml.ROW_SAMPLE, labels); 100 | System.out.println("Knn training result: " + success); 101 | // knn.save("D:/bp.xml");//存储模型 102 | 103 | // find the nearest neighbours of test data 104 | Mat results = new Mat(); 105 | Mat neighborResponses = new Mat(); 106 | Mat dists = new Mat(); 107 | knn.findNearest(testData, K, results, neighborResponses, dists); 108 | System.out.println("results:\n" + results.dump()); 109 | System.out.println("Knn neighborResponses:\n" + neighborResponses.dump()); 110 | System.out.println("dists:\n" + dists.dump()); 111 | for (int i = 0; i < results.height(); i++) { 112 | if (results.get(i, 0)[0] == 0) 113 | System.out.println("Boy\n"); 114 | if (results.get(i, 0)[0] == 1) 115 | System.out.println("Girl\n"); 116 | } 117 | 118 | return results; 119 | } 120 | ``` 121 | ## // 逻辑回归 122 | ``` 123 | public static Mat MyLogisticRegression(Mat trainingData, Mat labels, Mat testData) { 124 | LogisticRegression lr = LogisticRegression.create(); 125 | 126 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 127 | boolean success = lr.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 128 | System.out.println("LogisticRegression training result: " + success); 129 | // lr.save("D:/bp.xml");//存储模型 130 | 131 | Mat responseMat = new Mat(); 132 | float response = lr.predict(testData, responseMat, 0); 133 | System.out.println("LogisticRegression responseMat:\n" + responseMat.dump()); 134 | for (int i = 0; i < responseMat.height(); i++) { 135 | if (responseMat.get(i, 0)[0] == 0) 136 | System.out.println("Boy\n"); 137 | if (responseMat.get(i, 0)[0] == 1) 138 | System.out.println("Girl\n"); 139 | } 140 | return responseMat; 141 | } 142 | ``` 143 | ## // 贝叶斯 144 | ``` 145 | public static Mat MyNormalBayes(Mat trainingData, Mat labels, Mat testData) { 146 | NormalBayesClassifier nb = NormalBayesClassifier.create(); 147 | 148 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 149 | boolean success = nb.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 150 | System.out.println("NormalBayes training result: " + success); 151 | // nb.save("D:/bp.xml");//存储模型 152 | 153 | Mat responseMat = new Mat(); 154 | float response = nb.predict(testData, responseMat, 0); 155 | System.out.println("NormalBayes responseMat:\n" + responseMat.dump()); 156 | for (int i = 0; i < responseMat.height(); i++) { 157 | if (responseMat.get(i, 0)[0] == 0) 158 | System.out.println("Boy\n"); 159 | if (responseMat.get(i, 0)[0] == 1) 160 | System.out.println("Girl\n"); 161 | } 162 | return responseMat; 163 | } 164 | ``` 165 | ## // 随机森林 166 | ``` 167 | public static Mat MyRTrees(Mat trainingData, Mat labels, Mat testData) { 168 | RTrees rtrees = RTrees.create(); 169 | rtrees.setMaxDepth(4); 170 | rtrees.setMinSampleCount(2); 171 | rtrees.setRegressionAccuracy(0.f); 172 | rtrees.setUseSurrogates(false); 173 | rtrees.setMaxCategories(16); 174 | rtrees.setPriors(new Mat()); 175 | rtrees.setCalculateVarImportance(false); 176 | rtrees.setActiveVarCount(1); 177 | rtrees.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 5, 0)); 178 | TrainData tData = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 179 | boolean success = rtrees.train(tData.getSamples(), Ml.ROW_SAMPLE, tData.getResponses()); 180 | System.out.println("Rtrees training result: " + success); 181 | // rtrees.save("D:/bp.xml");//存储模型 182 | 183 | Mat responseMat = new Mat(); 184 | rtrees.predict(testData, responseMat, 0); 185 | System.out.println("Rtrees responseMat:\n" + responseMat.dump()); 186 | for (int i = 0; i < responseMat.height(); i++) { 187 | if (responseMat.get(i, 0)[0] == 0) 188 | System.out.println("Boy\n"); 189 | if (responseMat.get(i, 0)[0] == 1) 190 | System.out.println("Girl\n"); 191 | } 192 | return responseMat; 193 | } 194 | ``` 195 | ## // 支持向量机 196 | ``` 197 | public static Mat MySvm(Mat trainingData, Mat labels, Mat testData) { 198 | SVM svm = SVM.create(); 199 | svm.setKernel(SVM.LINEAR); 200 | svm.setType(SVM.C_SVC); 201 | TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 1000, 0); 202 | svm.setTermCriteria(criteria); 203 | svm.setGamma(0.5); 204 | svm.setNu(0.5); 205 | svm.setC(1); 206 | 207 | TrainData td = TrainData.create(trainingData, Ml.ROW_SAMPLE, labels); 208 | boolean success = svm.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses()); 209 | System.out.println("Svm training result: " + success); 210 | // svm.save("D:/bp.xml");//存储模型 211 | // svm.load("D:/bp.xml");//读取模型 212 | 213 | Mat responseMat = new Mat(); 214 | svm.predict(testData, responseMat, 0); 215 | System.out.println("SVM responseMat:\n" + responseMat.dump()); 216 | for (int i = 0; i < responseMat.height(); i++) { 217 | if (responseMat.get(i, 0)[0] == 0) 218 | System.out.println("Boy\n"); 219 | if (responseMat.get(i, 0)[0] == 1) 220 | System.out.println("Girl\n"); 221 | } 222 | return responseMat; 223 | } 224 | ``` 225 | ## // SGD支持向量机 226 | ``` 227 | public static Mat MySvmsgd(Mat trainingData, Mat labels, Mat testData) { 228 | SVMSGD Svmsgd = SVMSGD.create(); 229 | TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 1000, 0); 230 | Svmsgd.setTermCriteria(criteria); 231 | Svmsgd.setInitialStepSize(2); 232 | Svmsgd.setSvmsgdType(SVMSGD.SGD); 233 | Svmsgd.setMarginRegularization(0.5f); 234 | boolean success = Svmsgd.train(trainingData, Ml.ROW_SAMPLE, labels); 235 | System.out.println("SVMSGD training result: " + success); 236 | // svm.save("D:/bp.xml");//存储模型 237 | // svm.load("D:/bp.xml");//读取模型 238 | 239 | Mat responseMat = new Mat(); 240 | Svmsgd.predict(testData, responseMat, 0); 241 | System.out.println("SVMSGD responseMat:\n" + responseMat.dump()); 242 | for (int i = 0; i < responseMat.height(); i++) { 243 | if (responseMat.get(i, 0)[0] == 0) 244 | System.out.println("Boy\n"); 245 | if (responseMat.get(i, 0)[0] == 1) 246 | System.out.println("Girl\n"); 247 | } 248 | return responseMat; 249 | } 250 | ``` --------------------------------------------------------------------------------