上个月在网上看到一个用web实现简单AR效果的文章,然后自己一路折腾,最后折腾出来一个 Asp.net+WebSocket+Emgucv实时人脸识别的东西,网上也有不少相关资料,有用winform的也有asp.net的。其实人脸识别技术早就成熟了,就是没机会接触这方面。百度了一下 找到好多,JqueryFaceDetection,face++,face core,opencv,emgucv等等,这些我都折腾了一遍,并不能很好的满足我的需求,我就是想像手机QQ里边的拍照的时候能识别到人脸并且对图像做一些处理。后来找到了一个用winform+emgucv实现的例子,我就想着怎么给弄web上。后来又看到一篇用websocket实现的例子,就结合了一下。

我自己做的这个有相当多的代码都是网上的直接拿来用了,对我来说,websocket和emgucv这两个东西都是第一次接触,有不少的坑,尤其这个emgucv!!,各个版本差别巨大,从2.4到3.2这几个版本我几乎都下载过,最终是用的3.1的。好了,下面进入正题,源码我已经放在github了,https://github.com/13005463562/FaceWeb 。其中NewFaceWeb是web端,NewFace是服务端。想试一下效果的可以戳这里(要用火狐浏览器,谷歌太坑,强制要用https才能打开摄像头,其他浏览器还存在兼容性问题,其实一些手机浏览器UC或者火狐也行,但是我不会调样式。:( ,对于没有录入姓名的人呢,只能出现一个方框,可以点截图(等你的脸出现方框的时候截图),然后录入你的姓名,就可以把你的名字也识别出来。

  一.整体介绍

首先下载emgucv3.1,我下载的是第一个297M那个。下载之后解压,需要用到bin下的x64文件夹,注意不是根目录下的x64。 Emgu.CV.Example 里边有一些关于emgucv的例子,都是按照那个写的代码,可以看看。

在前端利用canvas获取摄像头的图像信息,通过websocket把每一帧数据传到服务端,服务端拿到的是byte[]数据,要转换成需要的格式再识别到你的脸,然后去人脸训练库中比较,找出最像你的那个样本的姓名(相似度太低则为空),最后把你的脸的位置(左上角坐标和宽高)和姓名返回前端。前端拿到返回数据,在canvas上画出方框和姓名,ok,完事。

 二.前端实现

首先是html代码,使用H5中的video和canvas:

  1. <div>
  2. <div id='frame' style="position:relative;">
  3. <video style='position:absolute;top:0px;left:0px;z-index:2;' id="live" width="320" height="240" autoplay></video>
  4. <canvas style='position:absolute;top:242px;left:0px; z-index:170;' width="320" id="canvasFace" height="240"></canvas>
  5. <canvas style='position:absolute;top:242px;left:0px; z-index:11;' width="320" id="canvas" height="240"></canvas>
  6. </div>
  7. </div>

接着放js代码(从别人那搬来的=-=), 先是要打开摄像头,打开成功了就开启websocket,把一帧图像数据转成base64形式顺便压缩一下,压缩很重要,在本机测无所谓,但要放服务器网络延迟太高,每次前后台交互一两秒。。。压缩比0.5即可把延迟降低到300-400毫秒,这样就很流畅啦.

  1. $(function () {
  2. var video = $('#live').get()[0],
  3. canvas = $('#canvas'),
  4. ctx = canvas.get()[0].getContext('2d'),
  5. canvasFace = $('#canvasFace'),
  6. //canvasFace1 = document.getElementById("canvasFace");
  7. ctx2 = canvasFace.get()[0].getContext('2d'),
  8. canSend = true;
  9.  
  10. if (navigator.getUserMedia) { // Standard
  11. navigator.getUserMedia({ "video": true }, function (stream) {
  12. video.src = webkitURL.createObjectURL(stream);
  13. // video.play();
  14. startWS();
  15. }, errBack);
  16. } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
  17. navigator.webkitGetUserMedia({ "video": true }, function (stream) {
  18. video.src = window.webkitURL.createObjectURL(stream);
  19. // video.play();
  20. startWS();
  21. }, errBack);
  22. }
  23. else if (navigator.mozGetUserMedia) { // Firefox-prefixed
  24. navigator.mozGetUserMedia({ "video": true }, function (stream) {
  25. video.src = window.URL.createObjectURL(stream);
  26. //video.play();
  27. startWS();
  28. }, errBack);
  29. };
  30.  
  31. function errBack() {
  32. console.log('err');
  33. }
  34.  
  35. var _draw = function (pArr) {
  36. canvasFace[0].height = canvasFace[0].height;//重设height以清除画布
  37. ctx2.strokeStyle = "#EEEE00";
  38. ctx2.fillStyle = 'rgba(0,0,0,0.0)';
  39. ctx2.lineWidth = 2;
  40.  
  41. //设置字体样式
  42. ctx2.font = "30px Courier New";
  43. //设置字体填充颜色
  44. ctx2.fillStyle = "red";
  45. //ctx2.clearRect(0, 0, 320, 240);
  46. if (pArr == "[]") {
  47. return;
  48. }
  49.  
  50. var obj = $.parseJSON(pArr);
  51. for (var i = 0, l = obj.length; i < l; i++) {
  52.  
  53. var left = obj[i].X; //左上角x坐标
  54. var top = obj[i].Y;//左上角y坐标
  55. var width = obj[i].W; //宽
  56. var height = obj[i].H;//高
  57. var name = obj[i].N;//姓名
  58.  
  59. //画方框
  60. ctx2.moveTo(left, top);
  61. ctx2.lineTo(left + width, top);
  62. ctx2.lineTo(left + width, top + height);
  63. ctx2.lineTo(left, top + height);
  64. ctx2.lineTo(left, top);
  65. ctx2.stroke();
  66.  
  67. //从坐标点(50,50)开始绘制姓名
  68. ctx2.fillText(name, left - 30, top - 30);
  69. }
  70.  
  71. };
  72.  
  73. var startWS = function () {
  74. var ws = new WebSocket("ws://119.23.237.231:8082/Handler/GetFacePosition.ashx");
  75. ws.onopen = function () {
  76. console.log('Opened WS!');
  77.  
  78. };
  79. ws.onmessage = function (msg) {
  80. _draw(msg.data);
  81. canSend = true;
  82.  
  83. //记录每次连接的时间
  84. //var timestamp = new Date().getTime();
  85. //console.log("end=" + timestamp);
  86. };
  87. ws.onclose = function (msg) {
  88. console.log('socket close!');
  89. };
  90. var timer = setInterval(function () {
  91. ctx.drawImage(video, 0, 0, 320, 240);
  92. if (ws.readyState == WebSocket.OPEN && canSend) {
  93. canSend = false;
  94. var data = canvas.get()[0].toDataURL('image/jpeg', 0.5), //把画布转base64 压缩比例0.5
  95. newblob = dataURItoBlob(data);
  96.  
  97. ws.send(newblob);
  98. //ws.send("123");
  99. }
  100. }, 60);
  101. };
  102. });

function dataURItoBlob(dataURI) {
                  var byteString = atob(dataURI.split(',')[1]),
                  mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0],
                  ab = new ArrayBuffer(byteString.length),
                  ia = new Uint8Array(ab);
                  for (var i = 0; i < byteString.length; i++) {
                               ia[i] = byteString.charCodeAt(i);
                            }
                   return new Blob([ab], { type: mimeString });
                  }

  1.  

前端大概就这样子了,发送数据,接收数据,画图。仔细看一下,挺简单的。

二.服务端实现

服务端相对要复杂点了,我就大致讲一下怎么处理的,说说遇到的一些坑,详细的实现看源码就行了。

我用的asp.net MVC,需要引用emgucv的一些dll,Emgu.CV.UI,Emgu.CV.World,ZedGraph  ,这些在下载的emgucv中bin目录下都能找到,找不到就是版本下载错了。

首先当然是接收数据,用ashx实现的,rootPath是根目录路径,到时候需要把人脸样本(也就是你录入的脸的图像)文件夹放在项目根目录,还有一个人脸分类器的xml文件,也放在根目录。在调用emgucv的方法时会用到。

  1. private static string rootPath;
  2. private int _maxBufferSize = 256 * 1024;
  3.  
  4. public void ProcessRequest(HttpContext context)
  5. {
  6.  
  7. if (context.IsWebSocketRequest)
  8. {
  9. rootPath = context.Request.PhysicalApplicationPath;
  10.  
  11. context.AcceptWebSocketRequest(ProcessWSChat);
  12. }
  13. }

接着是实现websocket的代码,我就不多说了,还是搬代码:

  1. private async Task ProcessWSChat(AspNetWebSocketContext context)
  2. {
  3. try
  4. {
  5. WebSocket socket = context.WebSocket;
  6.  
  7. byte[] receiveBuffer = new byte[_maxBufferSize];
  8. ArraySegment<byte> buffer = new ArraySegment<byte>(receiveBuffer);
  9.  
  10. while (socket.State == WebSocketState.Open)
  11. {
  12. WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
  13.  
  14. if (result.MessageType == WebSocketMessageType.Close)
  15. {
  16. await socket.CloseAsync(
  17. result.CloseStatus.GetValueOrDefault(),
  18. result.CloseStatusDescription,
  19. CancellationToken.None);
  20. break;
  21. }
  22.  
  23. int offset = result.Count;
  24.  
  25. while (result.EndOfMessage == false)
  26. {
  27. result = await socket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer, offset, _maxBufferSize - offset), CancellationToken.None);
  28. offset += result.Count;
  29. }
  30.  
  31. if (result.MessageType == WebSocketMessageType.Binary && offset != 0)
  32. {
  33.  
  34. ArraySegment<byte> newbuff = new ArraySegment<byte>(Encoding.UTF8.GetBytes(FaceDetectionDetail(receiveBuffer, offset)));
  35. await socket.SendAsync(newbuff, WebSocketMessageType.Text, true, CancellationToken.None);
  36.  
  37. }
  38. }
  39. }
  40. catch (Exception e)
  41. {
  42. var err = e.Message;
  43. Com.Other.AddLog(err);
  44. }
  45. }

然后是调方法得到人脸数据,可以是多个脸,这里的把byte[]转Mat可是费了我好大功夫,最开始找不到简单的方法,只能傻乎乎生成图片到本地再去读取,效率低下,最终是在一个英语网站(讲真。。英语水平太低,都是蒙的)里边找到这个方法:

  1. private static string FaceDetectionDetail(byte[] data, int plength)
  2. {
  3. StringBuilder sb = new StringBuilder();
  4. sb.Append("[");
  5.  
  6. //把byte[]转成mat 找了好久找到的方法
  7. Image img =Com.Other. GetImageByBytes(data);
  8. Bitmap bmpImage = new Bitmap(img);
  9. Emgu.CV.Image<Bgr, Byte> currentFrame = new Emgu.CV.Image<Bgr, Byte>(bmpImage);
  10. Mat invert = new Mat();
  11. CvInvoke.BitwiseAnd(currentFrame, currentFrame, invert);
  12.  
  13. if (invert != null)
  14. {
  15. Com.KingFaceDetect.faceDetectedObj faces = Run1(invert); //得到识别到的脸
  16. for (int i = 0; i < faces.facesRectangle.Count; i++)
  17. {
  18. sb.AppendFormat("{{\"X\":{0},\"Y\":{1},\"W\":{2},\"H\":{3},\"N\":\"{4}\"}},", faces.facesRectangle[i].X, faces.facesRectangle[i].Y, faces.facesRectangle[i].Width, faces.facesRectangle[i].Height, faces.names[i]);
  19. }
  20.  
  21. if (sb[sb.Length - 1] == ',')
  22. {
  23. sb.Remove(sb.Length - 1, 1);
  24. }
  25.  
  26. }
  27.  
  28. sb.Append("]");
  29.  
  30. GC.Collect();
  31. //AddLog((System.Environment.TickCount - aa).ToString()); //单位毫秒
  32. return sb.ToString();
  33. }

再来看一下Run1这个方法,返回值是一个faceDetectedObj类型的,这是自己封装的一个类KingFaceDetect中的东西,它包含了识别的的脸部的坐标和这个人的姓名,从之前提到的winform版本中提出来的,基本没改。可以看到这里用了一个Application,因为在创建KingFaceDetect的时候会去加载人脸样本库,比较耗内存把,第一次没用全局,然后服务器都被搞崩了。

  1. static Com.KingFaceDetect.faceDetectedObj Run1(Mat image)
  2. {
  3.  
  4. if (HttpContext.Current.Application["detect"] == null)
  5. {
  6. HttpContext.Current.Application["detect"] = new Com.KingFaceDetect(); //存入全局 否则好像会报内存错误
  7. }
  8. Com.KingFaceDetect detect = (Com.KingFaceDetect)HttpContext.Current.Application["detect"];
  9. Com.KingFaceDetect.faceDetectedObj resut = detect.faceRecognize(image);
  10.  
  11. return resut;
  12. }

接下来就是这个核心的类了,KingFaceDetect  ,里边都有注释,懒得讲。。。。直接搬上来:,,在对比训练库得到姓名那一步,有个Distance,值越小越可能是同一个人,我自己改了下,大于4000就当没有,姓名返回“”。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. using Emgu.CV;
  7. using Emgu.CV.CvEnum;
  8. using Emgu.CV.Structure;
  9. using Emgu.Util;
  10. using Emgu.CV.Cuda;
  11. using System.Diagnostics;
  12. using Emgu.CV.UI;
  13. using System.Drawing;
  14. using System.IO;
  15.  
  16. namespace NewFace.Com
  17. {
  18. class KingFaceDetect
  19. {
  20. private string FaceSamplesPath =System.Web.HttpContext.Current. Server.MapPath("~/") + "\\trainedFaces"; //这个是训练库文件夹 需要手动复制到项目根目录下
  21. private CascadeClassifier faceClassifier = new CascadeClassifier(System.Web.HttpContext.Current. Server.MapPath("~/")+"\\haarcascade_frontalface_default.xml"); //这个文件也放根目录
  22. TrainedFaceRecognizer tfr;
  23.  
  24. public KingFaceDetect()
  25. {
  26. SetTrainedFaceRecognizer(FaceRecognizerType.EigenFaceRecognizer);
  27. }
  28.  
  29. /// <summary>
  30. /// 获取已保存的所有样本文件
  31. /// </summary>
  32. /// <returns></returns>
  33. public TrainedFileList SetSampleFacesList()
  34. {
  35. TrainedFileList tf = new TrainedFileList();
  36. DirectoryInfo di = new DirectoryInfo(FaceSamplesPath);
  37. int i = 0;
  38. foreach (FileInfo fi in di.GetFiles())
  39. {
  40. tf.trainedImages.Add(new Image<Gray, byte>(fi.FullName));
  41. tf.trainedLabelOrder.Add(i);
  42. tf.trainedFileName.Add(fi.Name.Split('_')[0]);
  43. i++;
  44. }
  45. return tf;
  46. }
  47.  
  48. /// <summary>
  49. /// 训练人脸识别器
  50. /// </summary>
  51. /// <param name="type"></param>
  52. /// <returns></returns>
  53. public TrainedFaceRecognizer SetTrainedFaceRecognizer(FaceRecognizerType type)
  54. {
  55. tfr = new TrainedFaceRecognizer();
  56. tfr.trainedFileList = SetSampleFacesList();
  57.  
  58. switch (type)
  59. {
  60. case FaceRecognizerType.EigenFaceRecognizer:
  61. tfr.faceRecognizer = new Emgu.CV.Face.EigenFaceRecognizer(80, double.PositiveInfinity);
  62.  
  63. break;
  64. case FaceRecognizerType.FisherFaceRecognizer:
  65. tfr.faceRecognizer = new Emgu.CV.Face.FisherFaceRecognizer(80, 3500);
  66. break;
  67. case FaceRecognizerType.LBPHFaceRecognizer:
  68. tfr.faceRecognizer = new Emgu.CV.Face.LBPHFaceRecognizer(1, 8, 8, 8, 100);
  69. break;
  70. }
  71. tfr.faceRecognizer.Train(tfr.trainedFileList.trainedImages.ToArray(), tfr.trainedFileList.trainedLabelOrder.ToArray());
  72. return tfr;
  73. }
  74.  
  75. /// <summary>
  76. /// 获取制定图片,识别出的人脸矩形框
  77. /// </summary>
  78. /// <param name="emguImage"></param>
  79. /// <returns></returns>
  80. public faceDetectedObj GetFaceRectangle(Mat emguImage)
  81. {
  82. faceDetectedObj fdo = new faceDetectedObj();
  83. fdo.originalImg = emguImage;
  84. List<Rectangle> faces = new List<Rectangle>();
  85. try
  86. {
  87. using (UMat ugray = new UMat())
  88. {
  89. CvInvoke.CvtColor(emguImage, ugray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);//灰度化图片
  90. CvInvoke.EqualizeHist(ugray, ugray);//均衡化灰度图片
  91.  
  92. Rectangle[] facesDetected = faceClassifier.DetectMultiScale(ugray, 1.1, 10, new Size(20, 20));
  93. faces.AddRange(facesDetected);
  94. }
  95. }
  96. catch (Exception ex)
  97. {
  98. }
  99. fdo.facesRectangle = faces;
  100.  
  101. return fdo;
  102. }
  103.  
  104. /// <summary>
  105. /// 人脸识别
  106. /// </summary>
  107. /// <param name="emguImage"></param>
  108. /// <returns></returns>
  109. public faceDetectedObj faceRecognize(Mat emguImage)
  110. {
  111. faceDetectedObj fdo = GetFaceRectangle(emguImage);
  112. Image<Gray, byte> tempImg = fdo.originalImg.ToImage<Gray, byte>();
  113. #region 给识别出的所有人脸画矩形框
  114. using (Graphics g = Graphics.FromImage(fdo.originalImg.Bitmap))
  115. {
  116. foreach (Rectangle face in fdo.facesRectangle)
  117. {
  118.  
  119. Image<Gray, byte> GrayFace = tempImg.Copy(face).Resize(100, 100, Emgu.CV.CvEnum.Inter.Cubic);
  120. GrayFace._EqualizeHist();//得到均衡化人脸的灰度图像
  121.  
  122. #region 得到匹配姓名
  123. Emgu.CV.Face.FaceRecognizer.PredictionResult pr = tfr.faceRecognizer.Predict(GrayFace);
  124. string name = "";
  125.  
  126. //Distance越小表示 越可能是同一个人
  127. if (pr.Distance <4000)
  128. {
  129. name = tfr.trainedFileList.trainedFileName[pr.Label].ToString();
  130. }
  131.  
  132. #endregion
  133. fdo.names.Add(name);
  134. }
  135. }
  136.  
  137. #endregion
  138. return fdo;
  139. }
  140.  
  141. #region 自定义类及访问类型
  142. public class TrainedFileList
  143. {
  144. public List<Image<Gray, byte>> trainedImages = new List<Image<Gray, byte>>();
  145. public List<int> trainedLabelOrder = new List<int>();
  146. public List<string> trainedFileName = new List<string>();
  147. }
  148.  
  149. public class TrainedFaceRecognizer
  150. {
  151. public Emgu.CV.Face.FaceRecognizer faceRecognizer;
  152. public TrainedFileList trainedFileList;
  153. }
  154.  
  155. public class faceDetectedObj
  156. {
  157. public Mat originalImg;
  158. public List<Rectangle> facesRectangle;
  159. public List<string> names = new List<string>();
  160. }
  161.  
  162. public enum FaceRecognizerType
  163. {
  164. EigenFaceRecognizer = 0,
  165. FisherFaceRecognizer = 1,
  166. LBPHFaceRecognizer = 2,
  167. };
  168.  
  169. #endregion
  170. }
  171.  
  172. }

OK,核心代码都齐了,但是你想点击Debug来跑一个那还不行,,你会发现在调用emgucv的时候会报错:

“Emgu.CV.CvInvoke”的类型初始值设定项引发异常 !!!!!!!!!

就是这个异常,几乎伴随整个项目,关于这个异常,稍后我再总结一下。在代码都完事的时候在vs上跑不起来,很伤心啊,,很绝望,,想了好久好久,会不会是vs根本就没把x64文件夹下的dll加载起来?,把项目发布到iis上跑了一下,居然成功了!别提我有多鸡冻了。所以呢,就不在vs上调试了,直接放服务器上跑,在慢慢调试。下面是发布后的样子:

  二.总结

1.对于上边提到的那个异常,首先是和.net版本有关,当时我先整的winform版的人脸识别,用的.net4.5,就报那个异常,一直降级降到3.5才ok。但是在写web服务端的时候,用的.net4.5却又完全没问题。我也很蒙。还有一个原因就是之前提到的x64文件夹,要把整个文件夹放到应用程序的bin目录下(把整个文件夹放进去就行,不要把里边的dll复制出来到bin下),大概700多M。

2.emgucv各个版本差别较大,在这个版本能用的代码,到其他版本可能根本用不了。

暂时先这些吧,有什么疏忽的以后再补上。本来还想用Xamarin.Android做个安卓app的,但是。。。好难啊,就一个socket就遇到了麻烦。有懂Xamarin的大神能指点指点吗?

Asp.net+WebSocket+Emgucv实时人脸识别的更多相关文章

  1. 使用dlib中的深度残差网络(ResNet)实现实时人脸识别

    opencv中提供的基于haar特征级联进行人脸检测的方法效果非常不好,本文使用dlib中提供的人脸检测方法(使用HOG特征或卷积神经网方法),并使用提供的深度残差网络(ResNet)实现实时人脸识别 ...

  2. Opencv摄像头实时人脸识别

    Introduction 网上存在很多人脸识别的文章,这篇文章是我的一个作业,重在通过摄像头实时采集人脸信息,进行人脸检测和人脸识别,并将识别结果显示在左上角. 利用 OpenCV 实现一个实时的人脸 ...

  3. c# 利用AForge和百度AI开发实时人脸识别

    baiduAIFaceIdentify项目是C#语言,集成百度AI的SDK利用AForge开发的实时人脸识别的小demo,里边包含了人脸检测识别,人脸注册,人脸登录等功能 人脸实时检测识别功能 思路是 ...

  4. face_recognition实时人脸识别

    具体安装移步:https://www.cnblogs.com/ckAng/p/10981025.html 更多操作移步:https://github.com/ageitgey/face_recogni ...

  5. Python 3 利用 Dlib 19.7 实现摄像头人脸识别

    0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,提取人脸特征,通过计算欧氏距离来和预存的人脸特征进行对比,达到人脸识别的目的: 可以自动从摄像头中抠取人脸图片存储到本地: 根据抠取的 ...

  6. TensorFlow人脸识别

    TensorFlow框架做实时人脸识别小项目(一)https://blog.csdn.net/Goerge_L/article/details/80208297 TensorFlow框架做实时人脸识别 ...

  7. Python3利用Dlib19.7实现摄像头人脸识别的方法

    0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,提取人脸特征,通过计算欧氏距离来和预存的人脸特征进行对比,达到人脸识别的目的: 可以自动从摄像头中抠取人脸图片存储到本地,然后提取构建 ...

  8. html5与EmguCV前后端实现——人脸识别篇(一)

    上个月因为出差的关系,断更了很久,为了补偿大家长久的等待,送上一个新的系列,之前几个系列也会抽空继续更新. 大概半年多前吧,因为工作需要,我开始研究图像识别技术.OpenCV在这方面已经有了很多技术积 ...

  9. asp.net 虹软 人脸识别 实现刷脸住宿、刷脸签到、刷脸进入等

    先看看效果图,我把demo改成自动运行了,暂时借用别人的图片: 最左侧的大图为选择上传的, 中间的小图是大图的脸, 右侧的大图是人脸文件夹中已经存在的,并且相似度较高的一张脸,也就是比对的结果. 先记 ...

随机推荐

  1. 洛谷AT2342 Train Service Planning(思维,动态规划,珂朵莉树)

    洛谷题目传送门 神仙思维题还是要写点东西才好. 建立数学模型 这种很抽象的东西没有式子描述一下显然是下不了手的. 因为任何位置都以\(k\)为周期,所以我们只用关心一个周期,也就是以下数都在膜\(k\ ...

  2. nfs的配置文件/etc/exports

    /etc/exports  文件格式 <输出目录> [客户端1 选项(访问权限,用户映射,其他)] [客户端2 选项(访问权限,用户映射,其他)] a. 输出目录:输出目录是指NFS系统中 ...

  3. 简单使用TFS管理源代码

    今天研究使用了一下TFS,主要是想管理源代码.不涉汲团队管理. 使用环境W10专业版  / VS2017 社区版 / SQLSERVER2016  / TFS2017 EXPRESS版本 1.下载和安 ...

  4. 「TJOI2015」线性代数 解题报告

    「TJOI2015」线性代数 和牛客某题很像 在和里面有\(B_{i,j}\)要求是\(A_i,A_j\)都为\(1\),和里面减去\(C_i\)要求\(A_i\)为\(1\),然后先把贡献也就是\( ...

  5. BZOJ3779重组病毒LCT

    题目描述 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒.实验在一个封闭 ...

  6. js jquery 判断元素是否在数组内

    js jquery 判断元素是否在数组内 一,js方法 var arr = ["a", "b", "c"]; // js arr.index ...

  7. 斯坦福大学公开课机器学习:advice for applying machine learning | learning curves (改进学习算法:高偏差和高方差与学习曲线的关系)

    绘制学习曲线非常有用,比如你想检查你的学习算法,运行是否正常.或者你希望改进算法的表现或效果.那么学习曲线就是一种很好的工具.学习曲线可以判断某一个学习算法,是偏差.方差问题,或是二者皆有. 为了绘制 ...

  8. org.apache.poi 读取数字问题

    默认呢,POI读取单元格内容为数字的话,自动搞成Dubbo类型的,比如这样: String value1 = row.getCell(0).getNumericCellValue()+"&q ...

  9. bzoj 4326: NOIP2015 运输计划(二分+树链剖分)

    传送门 题解: 树链剖分快速求解任意两点间的路径的权值和: 然后,二分答案: 此题的难点是如何快速求解重合路径? 差分数组可以否??? 在此之前先介绍一下相关变量: int fa[maxn]; int ...

  10. jmeter-实用插件

    1.官网下载插件管理工具 https://jmeter-plugins.org/downloads/all/ 2.将jar包放在jmeter的 lib/ext文件夹下 3.重启jmeter 4.点击“ ...