本文实现基于eigenface的人脸检测与识别。给定一个图像数据库,进行以下步骤:

  • 进行人脸检测,将检测出的人脸存入数据库2
  • 对数据库2进行人脸建模
  • 在测试集上进行recognition
本篇实现第一步:

  • 进行人脸检测,将检测出的人脸存入数据库2

环境:vs2010+opencv 2.4.6.0

特征:eigenface

Input:一个人脸数据库,15个人,每人20个样本(左右)。

Output:人脸检测,并识别出每张检测到的人脸。

===============================

本文完成第一步,数据预处理:自动检测所有文件夹中每个sample中的人脸,作为训练数据。

Input:一个color文件夹,每个文件夹中有1~N这N个子文件夹,每个子文件夹内有n张包括第n类人的照片,如图。

最终结果:

核心:face detection(detectAndDraw)

辅助:截图并保存部分图片(CutImg),文件夹内图片遍历(read_img),图片转换成相同大小(normalizeone)

括号内分别是函数名,下面分别给出代码及说明。

1. 遍历文件夹:CBrowseDir类和CStatDir类(具体见这篇),三个文件如下:

1.1 BrowseDir.h

[cpp] view plaincopy
  1. #pragma once
  2. #include "direct.h"
  3. #include "string.h"
  4. #include "io.h"
  5. #include "stdio.h"
  6. #include <vector>
  7. #include <iostream>
  8. using namespace std;
  9. class CBrowseDir
  10. {
  11. protected:
  12. char m_szInitDir[_MAX_PATH];
  13. public:
  14. CBrowseDir();
  15. bool SetInitDir(const char *dir);
  16. bool BeginBrowse(const char *filespec);
  17. vector<char*> BeginBrowseFilenames(const char *filespec);
  18. protected:
  19. bool BrowseDir(const char *dir,const char *filespec);
  20. vector<char*> GetDirFilenames(const char *dir,const char *filespec);
  21. virtual bool ProcessFile(const char *filename);
  22. virtual void ProcessDir(const char *currentdir,const char *parentdir);
  23. };

1.2 BrowseDir.cpp

[cpp] view plaincopy
  1. #include "BrowseDir.h"
  2. #include "direct.h"
  3. #include "string.h"
  4. #include "io.h"
  5. #include "stdio.h"
  6. #include <vector>
  7. #include <iostream>
  8. using namespace std;
  9. CBrowseDir::CBrowseDir()
  10. {
  11. getcwd(m_szInitDir,_MAX_PATH);
  12. int len=strlen(m_szInitDir);
  13. if (m_szInitDir[len-1] != '\\')
  14. strcat(m_szInitDir,"\\");
  15. }
  16. bool CBrowseDir::SetInitDir(const char *dir)
  17. {
  18. if (_fullpath(m_szInitDir,dir,_MAX_PATH) == NULL)
  19. return false;
  20. if (_chdir(m_szInitDir) != 0)
  21. return false;
  22. int len=strlen(m_szInitDir);
  23. if (m_szInitDir[len-1] != '\\')
  24. strcat(m_szInitDir,"\\");
  25. return true;
  26. }
  27. vector<char*>CBrowseDir:: BeginBrowseFilenames(const char *filespec)
  28. {
  29. ProcessDir(m_szInitDir,NULL);
  30. return GetDirFilenames(m_szInitDir,filespec);
  31. }
  32. bool CBrowseDir::BeginBrowse(const char *filespec)
  33. {
  34. ProcessDir(m_szInitDir,NULL);
  35. return BrowseDir(m_szInitDir,filespec);
  36. }
  37. bool CBrowseDir::BrowseDir(const char *dir,const char *filespec)
  38. {
  39. _chdir(dir);
  40. long hFile;
  41. _finddata_t fileinfo;
  42. if ((hFile=_findfirst(filespec,&fileinfo)) != -1)
  43. {
  44. do
  45. {
  46. if (!(fileinfo.attrib & _A_SUBDIR))
  47. {
  48. char filename[_MAX_PATH];
  49. strcpy(filename,dir);
  50. strcat(filename,fileinfo.name);
  51. cout << filename << endl;
  52. if (!ProcessFile(filename))
  53. return false;
  54. }
  55. } while (_findnext(hFile,&fileinfo) == 0);
  56. _findclose(hFile);
  57. }
  58. _chdir(dir);
  59. if ((hFile=_findfirst("*.*",&fileinfo)) != -1)
  60. {
  61. do
  62. {
  63. if ((fileinfo.attrib & _A_SUBDIR))
  64. {
  65. if (strcmp(fileinfo.name,".") != 0 && strcmp
  66. (fileinfo.name,"..") != 0)
  67. {
  68. char subdir[_MAX_PATH];
  69. strcpy(subdir,dir);
  70. strcat(subdir,fileinfo.name);
  71. strcat(subdir,"\\");
  72. ProcessDir(subdir,dir);
  73. if (!BrowseDir(subdir,filespec))
  74. return false;
  75. }
  76. }
  77. } while (_findnext(hFile,&fileinfo) == 0);
  78. _findclose(hFile);
  79. }
  80. return true;
  81. }
  82. vector<char*> CBrowseDir::GetDirFilenames(const char *dir,const char *filespec)
  83. {
  84. _chdir(dir);
  85. vector<char*>filename_vec;
  86. filename_vec.clear();
  87. long hFile;
  88. _finddata_t fileinfo;
  89. if ((hFile=_findfirst(filespec,&fileinfo)) != -1)
  90. {
  91. do
  92. {
  93. if (!(fileinfo.attrib & _A_SUBDIR))
  94. {
  95. char *filename = new char[_MAX_PATH];
  96. strcpy(filename,dir);
  97. //int st = 0;   while (dir[st++]!='\0');
  98. strcat(filename,fileinfo.name); //filename[st]='\0';
  99. filename_vec.push_back(filename);
  100. }
  101. } while (_findnext(hFile,&fileinfo) == 0);
  102. _findclose(hFile);
  103. }
  104. _chdir(dir);
  105. if ((hFile=_findfirst("*.*",&fileinfo)) != -1)
  106. {
  107. do
  108. {
  109. if ((fileinfo.attrib & _A_SUBDIR))
  110. {
  111. if (strcmp(fileinfo.name,".") != 0 && strcmp
  112. (fileinfo.name,"..") != 0)
  113. {
  114. char subdir[_MAX_PATH];
  115. strcpy(subdir,dir);
  116. strcat(subdir,fileinfo.name);
  117. strcat(subdir,"\\");
  118. ProcessDir(subdir,dir);
  119. return GetDirFilenames(subdir,filespec);
  120. }
  121. }
  122. } while (_findnext(hFile,&fileinfo) == 0);
  123. _findclose(hFile);
  124. }
  125. return filename_vec;
  126. }
  127. bool CBrowseDir::ProcessFile(const char *filename)
  128. {
  129. return true;
  130. }
  131. void CBrowseDir::ProcessDir(const char
  132. *currentdir,const char *parentdir)
  133. {
  134. }

1.3 StatDir.h

[cpp] view plaincopy
  1. #pragma once
  2. #include "browsedir.h"
  3. class CStatDir:public CBrowseDir
  4. {
  5. protected:
  6. int m_nFileCount;   //保存文件个数
  7. int m_nSubdirCount; //保存子目录个数
  8. public:
  9. CStatDir()
  10. {
  11. m_nFileCount=m_nSubdirCount=0;
  12. }
  13. int GetFileCount()
  14. {
  15. return m_nFileCount;
  16. }
  17. int GetSubdirCount()
  18. {
  19. return m_nSubdirCount-1;
  20. }
  21. protected:
  22. virtual bool ProcessFile(const char *filename)
  23. {
  24. m_nFileCount++;
  25. return CBrowseDir::ProcessFile(filename);
  26. }
  27. virtual void ProcessDir
  28. (const char *currentdir,const char *parentdir)
  29. {
  30. m_nSubdirCount++;
  31. CBrowseDir::ProcessDir(currentdir,parentdir);
  32. }
  33. };

2. 辅助函数Prehelper.h, Prehelper.cpp:负责返回文件夹内所有图片(read_img),检测人脸(detectAndDraw并可以在原图中画出),截图(CutImg),提取(DetectandExtract)

2.1 Prehelper.h

[cpp] view plaincopy
  1. //preprocessing helper
  2. //@ Author : Rachel-Zhang
  3. #include "opencv2/core/core.hpp"
  4. #include "opencv2/highgui/highgui.hpp"
  5. #include "opencv2/contrib/contrib.hpp"
  6. #include <cv.h>
  7. #include <vector>
  8. #include <utility>
  9. using namespace cv;
  10. using namespace std;
  11. void normalizeone(const char* dir,IplImage* standard);
  12. void CutImg(IplImage* src, CvRect rect,IplImage* res);
  13. vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,
  14. CascadeClassifier& nestedCascade,
  15. double scale, bool tryflip,bool draw );
  16. IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade,
  17. CascadeClassifier& nestedCascade,
  18. double scale, bool tryflip);
  19. int read_img(const string& dir, vector<Mat> &images);
  20. vector<pair<char*,Mat>>  read_img(const string& dir);

2.2 Prehelper.cpp

[cpp] view plaincopy
  1. #include "Prehelper.h"
  2. #include "BrowseDir.h"
  3. #include "StatDir.h"
  4. #include <opencv2/core/core.hpp>
  5. #include <opencv2/highgui/highgui.hpp>
  6. #include <cv.h>
  7. using namespace cv;
  8. void normalizeone(const char* dir,IplImage* standard)
  9. {
  10. CStatDir statdir;
  11. if (!statdir.SetInitDir(dir))
  12. {
  13. puts("Dir not exist");
  14. return;
  15. }
  16. vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");
  17. int i;
  18. for (i=0;i<file_vec.size();i++)
  19. {
  20. IplImage* cur_img = cvLoadImage(file_vec[i],CV_LOAD_IMAGE_GRAYSCALE);
  21. //IplImage*cur_gray = cvCreateImage(cvGetSize(cur_img),cur_img->depth,1);
  22. cvResize(cur_img,standard,CV_INTER_AREA);
  23. //cvCvtColor(standard,cur_gray,CV_RGB2GRAY);
  24. //      cvNamedWindow("cur_img",CV_WINDOW_AUTOSIZE);
  25. //      cvNamedWindow("standard",CV_WINDOW_AUTOSIZE);
  26. //      cvShowImage("cur_img",cur_img);
  27. //      cvShowImage("standard",standard);
  28. //      cvWaitKey();
  29. cvSaveImage(file_vec[i],cur_img);
  30. }
  31. }
  32. void CutImg(IplImage* src, CvRect rect,IplImage* res)
  33. {
  34. CvSize imgsize;
  35. imgsize.height = rect.height;
  36. imgsize.width = rect.width;
  37. cvSetImageROI(src,rect);
  38. cvCopy(src,res);
  39. cvResetImageROI(res);
  40. }
  41. int read_img(const string& dir, vector<Mat> &images)
  42. {
  43. CStatDir statdir;
  44. if (!statdir.SetInitDir(dir.c_str()))
  45. {
  46. cout<<"Direct "<<dir<<"  not exist!"<<endl;
  47. return 0;
  48. }
  49. int cls_id = dir[dir.length()-1]-'0';
  50. vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");
  51. int i,s = file_vec.size();
  52. for (i=0;i<s;i++)
  53. {
  54. Mat graymat = imread(file_vec[i],0);
  55. //graymat.reshape(1,1);//flatten to one row
  56. images.push_back(graymat);
  57. }
  58. return s;
  59. }
  60. vector<pair<char*,Mat>>  read_img(const string& dir)
  61. {
  62. CStatDir statdir;
  63. pair<char*,Mat> pfi;
  64. vector<pair<char*,Mat>> Vp;
  65. if (!statdir.SetInitDir(dir.c_str()))
  66. {
  67. cout<<"Direct "<<dir<<"  not exist!"<<endl;
  68. return Vp;
  69. }
  70. int cls_id = dir[dir.length()-1]-'0';
  71. vector<char*>file_vec = statdir.BeginBrowseFilenames("*.*");
  72. int i,s = file_vec.size();
  73. for (i=0;i<s;i++)
  74. {
  75. pfi.first = file_vec[i];
  76. pfi.second = imread(file_vec[i]);
  77. Vp.push_back(pfi);
  78. }
  79. return Vp;
  80. }
  81. vector<Rect> detectAndDraw( Mat& img, CascadeClassifier& cascade,
  82. CascadeClassifier& nestedCascade,
  83. double scale, bool tryflip, bool draw )
  84. {
  85. int i = 0;
  86. double t = 0;
  87. vector<Rect> faces, faces2;
  88. const static Scalar colors[] =  { CV_RGB(0,0,255),
  89. CV_RGB(0,128,255),
  90. CV_RGB(0,255,255),
  91. CV_RGB(0,255,0),
  92. CV_RGB(255,128,0),
  93. CV_RGB(255,255,0),
  94. CV_RGB(255,0,0),
  95. CV_RGB(255,0,255)} ;
  96. Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
  97. cvtColor( img, gray, CV_BGR2GRAY );
  98. resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
  99. equalizeHist( smallImg, smallImg );
  100. t = (double)cvGetTickCount();
  101. cascade.detectMultiScale( smallImg, faces,
  102. 1.1, 2, 0
  103. |CV_HAAR_FIND_BIGGEST_OBJECT
  104. //|CV_HAAR_DO_ROUGH_SEARCH
  105. //|CV_HAAR_SCALE_IMAGE
  106. ,
  107. Size(30, 30) );
  108. if( tryflip )
  109. {
  110. flip(smallImg, smallImg, 1);
  111. cascade.detectMultiScale( smallImg, faces2,
  112. 1.1, 2, 0
  113. |CV_HAAR_FIND_BIGGEST_OBJECT
  114. //|CV_HAAR_DO_ROUGH_SEARCH
  115. //|CV_HAAR_SCALE_IMAGE
  116. ,
  117. Size(30, 30) );
  118. for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )
  119. {
  120. faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
  121. }
  122. }
  123. t = (double)cvGetTickCount() - t;
  124. printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
  125. if(draw)
  126. {
  127. for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
  128. {
  129. Mat smallImgROI;
  130. vector<Rect> nestedObjects;
  131. Point center;
  132. Scalar color = colors[i%8];
  133. int radius;
  134. double aspect_ratio = (double)r->width/r->height;
  135. rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),
  136. cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),
  137. color, 3, 8, 0);
  138. if( nestedCascade.empty() )
  139. continue;
  140. smallImgROI = smallImg(*r);
  141. nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
  142. 1.1, 2, 0
  143. |CV_HAAR_FIND_BIGGEST_OBJECT
  144. //|CV_HAAR_DO_ROUGH_SEARCH
  145. //|CV_HAAR_DO_CANNY_PRUNING
  146. //|CV_HAAR_SCALE_IMAGE
  147. ,
  148. Size(30, 30) );
  149. //draw eyes
  150. //         for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
  151. //         {
  152. //             center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
  153. //             center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
  154. //             radius = cvRound((nr->width + nr->height)*0.25*scale);
  155. //             circle( img, center, radius, color, 3, 8, 0 );
  156. //         }
  157. }
  158. cv::imshow( "result", img );
  159. }
  160. return faces;
  161. }
  162. IplImage* DetectandExtract(Mat& img, CascadeClassifier& cascade,
  163. CascadeClassifier& nestedCascade,
  164. double scale, bool tryflip)
  165. {
  166. vector<Rect> Rvec = detectAndDraw(img,cascade,nestedCascade,scale,tryflip,0);
  167. int i,maxxsize=0,id=-1,area;
  168. for (i=0;i<Rvec.size();i++)
  169. {
  170. area = Rvec[i].width*Rvec[i].height;
  171. if(maxxsize<area)
  172. {
  173. maxxsize = area;
  174. id = i;
  175. }
  176. }
  177. IplImage* transimg = cvCloneImage(&(IplImage)img);
  178. if(id!=-1)
  179. {
  180. CvSize imgsize;
  181. imgsize.height = Rvec[id].height;
  182. imgsize.width = Rvec[id].width;
  183. IplImage* res = cvCreateImage(imgsize,transimg->depth,transimg->nChannels);
  184. CutImg(transimg,Rvec[id],res);
  185. return res;
  186. }
  187. return NULL;
  188. }

3. 主函数

[cpp] view plaincopy
  1. //Detect.cpp
  2. //Preprocessing - Detect, Cut and Save
  3. //@Author : Rachel-Zhang
  4. #include "opencv2/objdetect/objdetect.hpp"
  5. #include "opencv2/highgui/highgui.hpp"
  6. #include "opencv2/imgproc/imgproc.hpp"
  7. #include <cctype>
  8. #include <iostream>
  9. #include <iterator>
  10. #include <stdio.h>
  11. #include "BrowseDir.h"
  12. #include "StatDir.h"
  13. #include "Prehelper.h"
  14. using namespace std;
  15. using namespace cv;
  16. #define CAM 2
  17. #define PHO 1
  18. #define K 5
  19. string cascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_frontalface_alt.xml";
  20. string nestedCascadeName = "E:/software/opencv2.4.6.0/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
  21. int main( )
  22. {
  23. CvCapture* capture = 0;
  24. Mat frame, frameCopy, image;
  25. string inputName;
  26. bool tryflip = false;
  27. int mode;
  28. CascadeClassifier cascade, nestedCascade;
  29. double scale = 1.0;
  30. if( !cascade.load( cascadeName ) ||!nestedCascade.load( nestedCascadeName))
  31. {
  32. cerr << "ERROR: Could not load classifier cascade or nestedCascade" << endl;//若出现该问题请去检查cascadeName,可能是opencv版本路径问题
  33. return -1;
  34. }
  35. //  printf("select the mode of detection: \n1: from picture\t 2: from camera\n");
  36. //  scanf("%d",&mode);
  37. char** pics = (char**) malloc(sizeof*pics);
  38. /************************************************************************/
  39. /*                                  detect face and save                                    */
  40. /************************************************************************/
  41. int i,j;
  42. cout<<"detect and save..."<<endl;
  43. const char dir[256] = "D:\\Face_recognition\\pic\\";
  44. string cur_dir;
  45. char id[5];
  46. for(i=1; i<=K; i++)
  47. {
  48. cur_dir = dir;
  49. _itoa(i,id,10);
  50. cur_dir.append("color\\");
  51. cur_dir.append(id);
  52. vector<pair<char*,Mat>> imgs=read_img(cur_dir);
  53. for(j=0;j<imgs.size();j++)
  54. {
  55. IplImage* res = DetectandExtract(imgs[j].second,cascade,nestedCascade,scale,tryflip);
  56. if(res)
  57. cvSaveImage(imgs[j].first,res);
  58. }
  59. }
  60. return 0;
  61. }

正确的输出就是一系列人脸检测时间,且原文件夹内的图片变成了检测出的人脸(如上面结果图所示)。

文章所用代码打包链接:http://download.csdn.net/detail/abcjennifer/7047853

from: http://blog.csdn.net/abcjennifer/article/details/20446077

opencv 人脸识别 (一)训练样本的处理相关推荐

  1. opencv 全志_移植opencv人脸识别到全志A10开发板上 +linux3.0内核

    移植opencv人脸识别 libz:    zlib-1.2.3 libjpeg:   jpegsrc.v6b libpng:   libpng-1.2.18 libyasm:   yasm-0.7. ...

  2. python人脸照片分类_Python OpenCV 人脸识别(一)

    前面介绍了Numpy模块,下面再介绍一个OpenCV模块,就基于这两个库看一下当下很火的人工智能是如何实现的,我们介绍几个:人脸识别(当下非常火的).音视频操作等等.今天先介绍一下静态图片的人脸识别, ...

  3. 图像识别——(java)opencv(人脸识别简单实现)

    人脸识别 package com.acts.opencv.demo;import javax.servlet.http.HttpServletRequest; import javax.servlet ...

  4. Python+OpenCV人脸识别签到考勤系统(新手入门)

    Python+OpenCV人脸识别签到考勤系统(新手入门) 前言 项目效果图 项目需要的环境 编译器 辅助开发QT-designer 项目配置 代码部分 核心代码 项目目录结构 后记 正式版改进 项目 ...

  5. python opencv人脸识别考勤系统的完整源码

    这篇文章主要介绍了python opencv人脸识别考勤系统的完整源码,本文给大家介绍的非常详细,希望对大家的学习或工作具有一定的参考借鉴价值. 代码如下: import wx import wx.g ...

  6. openCV人脸识别简单案例

    1 基础 我们使用机器学习的方法完成人脸检测,首先需要大量的正样本图像(面部图像)和负样本图像(不含面部的图像)来训练分类器.我们需要从其中提取特征.下图中的 Haar 特征会被使用,就像我们的卷积核 ...

  7. 【opencv人脸识别1】从图片中检测人脸

    [opencv人脸识别一]从图片中检测人脸 本系列主要讲述利用opencv实现人脸识别的相关知识,并给出实际代码.且循序渐进,由基础到复杂,从最基本的图片检测人脸到视频检测.识别人脸,再到较大型人脸数 ...

  8. OpenCV 人脸识别 源代码

    请直接查看原文 OpenCV 人脸识别 源代码 https://hotdog29.com/?p=553 在 2019年7月6日 上张贴 由 hotdog发表回复 opencv 人脸识别 在本教程中,您 ...

  9. 基于python opencv人脸识别的员工考勤系统

    WorkAttendanceSystem 一个基于opencv人脸识别的员工考勤系统,作者某双一流A类大学里的一流学生,写于2018/09/,python课设期间. 源代码详细解释请关注微信公众号: ...

  10. WPF编程--OpenCV人脸识别

    目录 1. 环境 2. NuGet导入依赖 3. 创建WriteableBitmapHelper.cs类 4. 编辑MainWindow.xaml.cs 5. 编辑MainWindow.xaml 1. ...

最新文章

  1. ubuntu16.04 server unrar解压rar文件提示command not found和解压tar.bz2文件
  2. 【随笔】JVM核心:JVM运行和类加载
  3. docker进阶 一键安装wordpress
  4. 菜鸟也玩WebMatrix
  5. 【Git】git stash应用场景
  6. 阿里云开源的Blink,计算能力很疯狂:一眨眼,全部都算好!
  7. 网络请求以及网络请求下载图片的工具类 android开发java工具类
  8. sar —— Linux 上最为全面的系统性能分析工具之一
  9. phpstorm 配置自带webserver ,配置根目录
  10. axios拦截器_Axios源码解析 —— 一个小而美的HttpClient
  11. java se用哪个eclipse_javaSE----eclipse的安装与使用
  12. FIT2CLOUD获网宿科技战略投资 深度聚焦混合云管理价值交付
  13. java word 分页显示_Java 在Word中插入分页符、分节符
  14. 数据类型--Number类型
  15. 鹏博士总经理陆榴遭免职 董事称事发突然
  16. miss工作室官宣加盟新公司是真的吗
  17. 联想电脑怎么录屏?这3个方法,轻松解决
  18. querylist V4 图片下载
  19. 程序设计思维与实践 CSP-M4
  20. Visio用UML2.5模板包下载地址

热门文章

  1. 深度丨110亿美金还不够,阿里使用这种AI手段创造更多广告收入
  2. 顶级风投First Round Capital对创业者的30个建议
  3. 数据结构与算法笔记(八)—— 插入排序
  4. 爬虫学习笔记(十六)—— Selenium
  5. oracle linux内存推荐分配,浅析Oracle 的体系架构及内存分配机制
  6. Java 调用 Kotlin
  7. android view setx,Android的setX()和setY()表现不可思议
  8. Matlab图像形态学处理—开操作和闭操作
  9. fluent计算进出口的流量差
  10. fileupload.class.php,php文件上传类