public void setValues(ObjectPosRect objectPosRect) { classid = objectPosRect.classid; confidence = objectPosRect.confidence; x1 = objectPosRect.x1; y1 = objectPosRect.y1; x2 = objectPosRect.x2; y2 = objectPosRect.y2; }
//显示检测后的图像 public void ShowPicture(Mat frameMat, List <ObjectPosRect> objectPosRects, ObjectPosRect objectPosRect, long toltalMillis) { if (showPicture && mainForm != null && outPictureBox != null && mainForm.Visible) { if (frameMat != null) { foreach (ObjectPosRect rect in objectPosRects) { Cv2.Rectangle(frameMat, new OpenCvSharp.Point(rect.x1, rect.y1), new OpenCvSharp.Point(rect.x2, rect.y2), new Scalar(0, 255, 0), 2, LineTypes.Link4); string msg = (string)this.labelNames.GetValue(rect.classid - 1) + ", " + rect.confidence.ToString("F2") + ", " + toltalMillis; Cv2.PutText(frameMat, msg, new OpenCvSharp.Point(rect.x1, rect.y1 + 20), HersheyFonts.HersheySimplex, 0.95, new Scalar(0, 0, 255)); } //计算对象的中心点,靠上方一些 int objCenterX = objectPosRect.x1 + (objectPosRect.x2 - objectPosRect.x1) / 2; int objCenterY = objectPosRect.y1 + (objectPosRect.y2 - objectPosRect.y1) / 3; objCenterX = detectionRect.x + objCenterX; objCenterY = detectionRect.y + objCenterY; //计算屏幕中心点 int screenCenterX = rawDetectionRect.x + rawDetectionRect.w / 2; int screenCenterY = rawDetectionRect.y + rawDetectionRect.h / 2; Cv2.Rectangle(frameMat, new OpenCvSharp.Point(objCenterX - 10 - detectionRect.x, objCenterY - 10 - detectionRect.y), new OpenCvSharp.Point(objCenterX + 10 - detectionRect.x, objCenterY + 10 - detectionRect.y), new Scalar(0, 255, 0), 2, LineTypes.Link4); Cv2.Rectangle(frameMat, new OpenCvSharp.Point(screenCenterX - 10 - detectionRect.x, screenCenterY - 10 - detectionRect.y), new OpenCvSharp.Point(screenCenterX + 10 - detectionRect.x, screenCenterY + 10 - detectionRect.y), new Scalar(0, 0, 255), 2, LineTypes.Link4); var frameBitmap = BitmapConverter.ToBitmap(frameMat); outPictureBox.Image?.Dispose(); outPictureBox.Image = frameBitmap; } } }
public long toltalMillis; //检测执行的时间 public void setValues(DetectionRect rawDetectionRect1, DetectionRect detectionRect1, Mat frameMat1, List <ObjectPosRect> objectPosRects1, ObjectPosRect maxConfidencePos1, int maxPersonW1, long toltalMillis1) { detectionResult4Rect = new DetectionResult4Rect(); detectionResult4Rect.rawDetectionRect = rawDetectionRect1; detectionResult4Rect.detectionRect = detectionRect1; detectionResult4Rect.maxConfidencePos = maxConfidencePos1; detectionResult4Rect.maxPersonW = maxPersonW1; frameMat = frameMat1; objectPosRects = objectPosRects1; toltalMillis = toltalMillis1; }
//使用AI模型检测屏幕,识别人员及位置 public DetectionResult DetectionScreen() { long toltalMillis = 0; long startTicks = DateTime.Now.Ticks; //保存所有检测对象及最大置信度对象的位置 DetectionResult detectionResult = new DetectionResult(); List <ObjectPosRect> objectPosRects = new List <ObjectPosRect>(); ObjectPosRect maxConfidencePos = new ObjectPosRect(); maxConfidencePos.setValues(0, 0, 0, 0, 0, 0); //拷贝需要检测屏幕区域的图像 //c#中处理图形,需要注意手动释放资源,及线程不安全的问题。 //System.Drawing.Bitmap bitmap = new Bitmap(this.detectionRect.w, this.detectionRect.h); //System.Drawing.Graphics graphics = Graphics.FromImage(bitmap); this.detectGraphics.CopyFromScreen(this.detectionRect.x, this.detectionRect.y, 0, 0, new System.Drawing.Size(this.detectionRect.w, this.detectionRect.h), CopyPixelOperation.SourceCopy); try { //注意这里不用using语句,因为会隐式释放图像对象,导致外面其他函数使用对象时无法访问。 Mat frameMat = BitmapConverter.ToMat(this.detectBitmap); if (frameMat != null && !frameMat.Empty()) { //屏幕截图和视频截图格式不一样,需要进行图像格式转换 Cv2.CvtColor(frameMat, frameMat, ColorConversionCodes.RGBA2RGB); // Convert Mat to batch of images var frameWidth = frameMat.Cols; var frameHeight = frameMat.Rows; //注意转换位输入数据时,最好保持原图大小,或者按比例缩放,相对于不按比例缩放,可以让识别准确率大幅提升。 //注意scaleFactor和scalemean参数设置,涉及模型输入数据归一化,严重影响模型准确率。 //using (var inputBlob = CvDnn.BlobFromImage(frameMat, 0.008, new OpenCvSharp.Size(320, 320), new Scalar(104, 117, 123), true, false)) //using (var inputBlob = CvDnn.BlobFromImage(frameMat, 0.008, new OpenCvSharp.Size(320, 320), new Scalar(103.939, 116.779, 123.68), true, false)) //using (var inputBlob = CvDnn.BlobFromImage(frameMat, 0.008, new OpenCvSharp.Size(frameWidth, frameHeight), new Scalar(103.939, 116.779, 123.68), true, false)) using (var inputBlob = CvDnn.BlobFromImage(frameMat, 1.0 / 127.5, new OpenCvSharp.Size(frameWidth, frameHeight), new Scalar(127.5, 127.5, 127.5), true, false)) //using (var inputBlob = CvDnn.BlobFromImage(frameMat, 1.0 / 255, new OpenCvSharp.Size(frameWidth, frameHeight), new Scalar(123.7, 116.3, 103.5), true, false)) { //使用AI模型推理检测图像 detectionNet.SetInput(inputBlob); var output = detectionNet.Forward(); //分析检测结果 var detectionMat = new Mat(output.Size(2), output.Size(3), MatType.CV_32F, output.Ptr(0)); for (int i = 0; i < detectionMat.Rows; i++) { float confidence = detectionMat.At <float>(i, 2); if (confidence > 0.60) { int classid = (int)detectionMat.At <float>(i, 1); //判断识别的类型,这个应用场景只显示识别的人,提升处理效率 //if (classid < this.labelNames.Length && (classid == 1 || classid != 1)) //if (classid < this.labelNames.Length && (classid == 1)) if (classid < this.labelNames.Length && (classid == 1)) { int x1 = (int)(detectionMat.At <float>(i, 3) * frameWidth); int y1 = (int)(detectionMat.At <float>(i, 4) * frameHeight); int x2 = (int)(detectionMat.At <float>(i, 5) * frameWidth); int y2 = (int)(detectionMat.At <float>(i, 6) * frameHeight); ObjectPosRect objectPosRect = new ObjectPosRect(); objectPosRect.setValues(classid, confidence, x1, y1, x2, y2); objectPosRects.Add(objectPosRect); //判断是否是最大人员模型; //为避免处理逻辑太复杂,最大模型宽度设置为一个常量; //if ((objectPosRect.x2 - objectPosRect.x1) < this.detectionRect.w / 3 && // (this.maxPersonPos.x2 - this.maxPersonPos.x1 < objectPosRect.x2 - objectPosRect.x1)) // this.maxPersonPos.setValues(objectPosRect); //为保障项目,排除太大或者太小的模型 if ((objectPosRect.x2 - objectPosRect.x1) <= 200 && (objectPosRect.x2 - objectPosRect.x1) >= 10 && (objectPosRect.y2 - objectPosRect.y1) <= 280 && (objectPosRect.y2 - objectPosRect.y1) >= 10) { //判断是否是游戏操作人,模型位置为屏幕游戏者位置 //游戏者的位置在屏幕下方靠左一点,大概 860/1920处 //另外游戏中左右摇摆幅度较大,所以x轴的兼容值要设置大一些。 if (Math.Abs(objectPosRect.x1 + (objectPosRect.x2 - objectPosRect.x1) / 2 - this.playerCentX) <= 100 && objectPosRect.y1 > this.detectionRect.h * 1 / 2 && Math.Abs(this.detectionRect.h - objectPosRect.y2) <= 10) { //排除游戏者自己 //var testi = 0; } else { //保存置信度最大的人员的位置,同时排除屏幕下方正中的游戏者自己 if (objectPosRect.confidence > maxConfidencePos.confidence) { maxConfidencePos.setValues(objectPosRect); } } } long endTicks = DateTime.Now.Ticks; toltalMillis = (endTicks - startTicks) / 10000; } } } } detectionResult.setValues(this.rawDetectionRect, this.detectionRect, frameMat, objectPosRects, maxConfidencePos, this.maxPersonW, toltalMillis); //图像显示放到其他线程中处理 //this.ShowPicture(frameMat, objectPosRects, maxConfidencePos, toltalMillis); } //Thread.Sleep(100); } catch (Exception ex) { Console.WriteLine(ex.Message); } //使用类属性,只创建了一个对象,不能手工释放 //graphics.Dispose(); //bitmap.Dispose(); return(detectionResult); }