728x90
반응형
728x170
[소스 이미지]
[결과 이미지]
TestProject.z01
10.00MB
TestProject.z02
10.00MB
TestProject.z03
10.00MB
TestProject.z04
10.00MB
TestProject.z05
10.00MB
TestProject.z06
10.00MB
TestProject.zip
5.49MB
▶ RectangleExtension.cs
using System.Drawing;
namespace TestProject
{
/// <summary>
/// 사각형 확장
/// </summary>
public static class RectangleExtension
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 영역 구하기 - GetArea(rectangle)
/// <summary>
/// 영역 구하기
/// </summary>
/// <param name="rectangle">사각형</param>
/// <returns>영역</returns>
public static float GetArea(this RectangleF rectangle)
{
return rectangle.Width * rectangle.Height;
}
#endregion
}
}
728x90
▶ YOLOModel.cs
using System.Collections.Generic;
namespace TestProject
{
/// <summary>
/// YOLO 모델
/// </summary>
public abstract class YOLOModel
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 너비 - Width
/// <summary>
/// 너비
/// </summary>
public abstract int Width { get; set; }
#endregion
#region 높이 - Height
/// <summary>
/// 높이
/// </summary>
public abstract int Height { get; set; }
#endregion
#region 깊이 - Depth
/// <summary>
/// 깊이
/// </summary>
public abstract int Depth { get; set; }
#endregion
#region 차원 - Dimension
/// <summary>
/// 차원
/// </summary>
public abstract int Dimension { get; set; }
#endregion
#region 스트라이드 배열 - StrideArray
/// <summary>
/// 스트라이드 배열
/// </summary>
public abstract float[] StrideArray { get; set; }
#endregion
#region 앵커 배열 - AnchorArray
/// <summary>
/// 앵커 배열
/// </summary>
public abstract float[][][] AnchorArray { get; set; }
#endregion
#region 도형 배열 - ShapeArray
/// <summary>
/// 도형 배열
/// </summary>
public abstract int[] ShapeArray { get; set; }
#endregion
#region 신뢰도 - Confidence
/// <summary>
/// 신뢰도
/// </summary>
public abstract float Confidence { get; set; }
#endregion
#region 다중 신뢰도 - MultipleConfidence
/// <summary>
/// 다중 신뢰도
/// </summary>
public abstract float MultipleConfidence { get; set; }
#endregion
#region 오버랩 - Overlap
/// <summary>
/// 오버랩
/// </summary>
public abstract float Overlap { get; set; }
#endregion
#region 출력 배열 - OutputArray
/// <summary>
/// 출력 배열
/// </summary>
public abstract string[] OutputArray { get; set; }
#endregion
#region 레이블 리스트 - LabelList
/// <summary>
/// 레이블 리스트
/// </summary>
public abstract List<YOLOLabel> LabelList { get; set; }
#endregion
#region 탐지 사용 여부 - UseDetect
/// <summary>
/// 탐지 사용 여부
/// </summary>
public abstract bool UseDetect { get; set; }
#endregion
}
}
300x250
▶ YOLOCOCOP5Model.cs
using System.Collections.Generic;
namespace TestProject
{
/// <summary>
/// YOLO COCO P5 모델
/// </summary>
public class YOLOCOCOP5Model : YOLOModel
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 너비 - Width
/// <summary>
/// 너비
/// </summary>
public override int Width { get; set; } = 640;
#endregion
#region 높이 - Height
/// <summary>
/// 높이
/// </summary>
public override int Height { get; set; } = 640;
#endregion
#region 깊이 - Depth
/// <summary>
/// 깊이
/// </summary>
public override int Depth { get; set; } = 3;
#endregion
#region 차원 - Dimension
/// <summary>
/// 차원
/// </summary>
public override int Dimension { get; set; } = 85;
#endregion
#region 스트라이드 배열 - StrideArray
/// <summary>
/// 스트라이드 배열
/// </summary>
public override float[] StrideArray { get; set; } = new float[] { 8, 16, 32 };
#endregion
#region 앵커 배열 - AnchorArray
/// <summary>
/// 앵커 배열
/// </summary>
public override float[][][] AnchorArray { get; set; } = new float[][][]
{
new float[][] { new float[] { 010, 13 }, new float[] { 016, 030 }, new float[] { 033, 023 } },
new float[][] { new float[] { 030, 61 }, new float[] { 062, 045 }, new float[] { 059, 119 } },
new float[][] { new float[] { 116, 90 }, new float[] { 156, 198 }, new float[] { 373, 326 } }
};
#endregion
#region 도형 배열 - ShapeArray
/// <summary>
/// 도형 배열
/// </summary>
public override int[] ShapeArray { get; set; } = new int[] { 80, 40, 20 };
#endregion
#region 신뢰도 - Confidence
/// <summary>
/// 신뢰도
/// </summary>
public override float Confidence { get; set; } = 0.20f;
#endregion
#region 다중 신뢰도 - MultipleConfidence
/// <summary>
/// 다중 신뢰도
/// </summary>
public override float MultipleConfidence { get; set; } = 0.25f;
#endregion
#region 오버랩 - Overlap
/// <summary>
/// 오버랩
/// </summary>
public override float Overlap { get; set; } = 0.45f;
#endregion
#region 출력 배열 - OutputArray
/// <summary>
/// 출력 배열
/// </summary>
public override string[] OutputArray { get; set; } = new[] { "output" };
#endregion
#region 레이블 리스트 - LabelList
/// <summary>
/// 레이블 리스트
/// </summary>
public override List<YOLOLabel> LabelList { get; set; } = new List<YOLOLabel>()
{
new YOLOLabel { ID = 1, Name = "person" },
new YOLOLabel { ID = 2, Name = "bicycle" },
new YOLOLabel { ID = 3, Name = "car" },
new YOLOLabel { ID = 4, Name = "motorcycle" },
new YOLOLabel { ID = 5, Name = "airplane" },
new YOLOLabel { ID = 6, Name = "bus" },
new YOLOLabel { ID = 7, Name = "train" },
new YOLOLabel { ID = 8, Name = "truck" },
new YOLOLabel { ID = 9, Name = "boat" },
new YOLOLabel { ID = 10, Name = "traffic light" },
new YOLOLabel { ID = 11, Name = "fire hydrant" },
new YOLOLabel { ID = 12, Name = "stop sign" },
new YOLOLabel { ID = 13, Name = "parking meter" },
new YOLOLabel { ID = 14, Name = "bench" },
new YOLOLabel { ID = 15, Name = "bird" },
new YOLOLabel { ID = 16, Name = "cat" },
new YOLOLabel { ID = 17, Name = "dog" },
new YOLOLabel { ID = 18, Name = "horse" },
new YOLOLabel { ID = 19, Name = "sheep" },
new YOLOLabel { ID = 20, Name = "cow" },
new YOLOLabel { ID = 21, Name = "elephant" },
new YOLOLabel { ID = 22, Name = "bear" },
new YOLOLabel { ID = 23, Name = "zebra" },
new YOLOLabel { ID = 24, Name = "giraffe" },
new YOLOLabel { ID = 25, Name = "backpack" },
new YOLOLabel { ID = 26, Name = "umbrella" },
new YOLOLabel { ID = 27, Name = "handbag" },
new YOLOLabel { ID = 28, Name = "tie" },
new YOLOLabel { ID = 29, Name = "suitcase" },
new YOLOLabel { ID = 30, Name = "frisbee" },
new YOLOLabel { ID = 31, Name = "skis" },
new YOLOLabel { ID = 32, Name = "snowboard" },
new YOLOLabel { ID = 33, Name = "sports ball" },
new YOLOLabel { ID = 34, Name = "kite" },
new YOLOLabel { ID = 35, Name = "baseball bat" },
new YOLOLabel { ID = 36, Name = "baseball glove" },
new YOLOLabel { ID = 37, Name = "skateboard" },
new YOLOLabel { ID = 38, Name = "surfboard" },
new YOLOLabel { ID = 39, Name = "tennis racket" },
new YOLOLabel { ID = 40, Name = "bottle" },
new YOLOLabel { ID = 41, Name = "wine glass" },
new YOLOLabel { ID = 42, Name = "cup" },
new YOLOLabel { ID = 43, Name = "fork" },
new YOLOLabel { ID = 44, Name = "knife" },
new YOLOLabel { ID = 45, Name = "spoon" },
new YOLOLabel { ID = 46, Name = "bowl" },
new YOLOLabel { ID = 47, Name = "banana" },
new YOLOLabel { ID = 48, Name = "apple" },
new YOLOLabel { ID = 49, Name = "sandwich" },
new YOLOLabel { ID = 50, Name = "orange" },
new YOLOLabel { ID = 51, Name = "broccoli" },
new YOLOLabel { ID = 52, Name = "carrot" },
new YOLOLabel { ID = 53, Name = "hot dog" },
new YOLOLabel { ID = 54, Name = "pizza" },
new YOLOLabel { ID = 55, Name = "donut" },
new YOLOLabel { ID = 56, Name = "cake" },
new YOLOLabel { ID = 57, Name = "chair" },
new YOLOLabel { ID = 58, Name = "couch" },
new YOLOLabel { ID = 59, Name = "potted plant" },
new YOLOLabel { ID = 60, Name = "bed" },
new YOLOLabel { ID = 61, Name = "dining table" },
new YOLOLabel { ID = 62, Name = "toilet" },
new YOLOLabel { ID = 63, Name = "tv" },
new YOLOLabel { ID = 64, Name = "laptop" },
new YOLOLabel { ID = 65, Name = "mouse" },
new YOLOLabel { ID = 66, Name = "remote" },
new YOLOLabel { ID = 67, Name = "keyboard" },
new YOLOLabel { ID = 68, Name = "cell phone" },
new YOLOLabel { ID = 69, Name = "microwave" },
new YOLOLabel { ID = 70, Name = "oven" },
new YOLOLabel { ID = 71, Name = "toaster" },
new YOLOLabel { ID = 72, Name = "sink" },
new YOLOLabel { ID = 73, Name = "refrigerator" },
new YOLOLabel { ID = 74, Name = "book" },
new YOLOLabel { ID = 75, Name = "clock" },
new YOLOLabel { ID = 76, Name = "vase" },
new YOLOLabel { ID = 77, Name = "scissors" },
new YOLOLabel { ID = 78, Name = "teddy bear" },
new YOLOLabel { ID = 79, Name = "hair drier" },
new YOLOLabel { ID = 80, Name = "toothbrush" }
};
#endregion
#region 탐지 사용 여부 - UseDetect
/// <summary>
/// 탐지 사용 여부
/// </summary>
public override bool UseDetect { get; set; } = true;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - YOLOCOCOP5Model()
/// <summary>
/// 생성자
/// </summary>
public YOLOCOCOP5Model()
{
}
#endregion
}
}
반응형
▶ YOLOCOCOP6Model.cs
using System.Collections.Generic;
namespace TestProject
{
/// <summary>
/// YOLO COCO P6 모델
/// </summary>
public class YOLOCOCOP6Model : YOLOModel
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 너비 - Width
/// <summary>
/// 너비
/// </summary>
public override int Width { get; set; } = 1280;
#endregion
#region 높이 - Height
/// <summary>
/// 높이
/// </summary>
public override int Height { get; set; } = 1280;
#endregion
#region 깊이 - Depth
/// <summary>
/// 깊이
/// </summary>
public override int Depth { get; set; } = 3;
#endregion
#region 차원 - Dimension
/// <summary>
/// 차원
/// </summary>
public override int Dimension { get; set; } = 85;
#endregion
#region 스트라이드 배열 - StrideArray
/// <summary>
/// 스트라이드 배열
/// </summary>
public override float[] StrideArray { get; set; } = new float[] { 8, 16, 32, 64 };
#endregion
#region 앵커 배열 - AnchorArray
/// <summary>
/// 앵커 배열
/// </summary>
public override float[][][] AnchorArray { get; set; } = new float[][][]
{
new float[][] { new float[] { 019, 027 }, new float[] { 044, 040 }, new float[] { 038, 094 } },
new float[][] { new float[] { 096, 068 }, new float[] { 086, 152 }, new float[] { 180, 137 } },
new float[][] { new float[] { 140, 301 }, new float[] { 303, 264 }, new float[] { 238, 542 } },
new float[][] { new float[] { 436, 615 }, new float[] { 739, 380 }, new float[] { 925, 792 } }
};
#endregion
#region 도형 배열 - ShapeArray
/// <summary>
/// 도형 배열
/// </summary>
public override int[] ShapeArray { get; set; } = new int[] { 160, 80, 40, 20 };
#endregion
#region 신뢰도 - Confidence
/// <summary>
/// 신뢰도
/// </summary>
public override float Confidence { get; set; } = 0.20f;
#endregion
#region 다중 신뢰도 - MultipleConfidence
/// <summary>
/// 다중 신뢰도
/// </summary>
public override float MultipleConfidence { get; set; } = 0.25f;
#endregion
#region 오버랩 - Overlap
/// <summary>
/// 오버랩
/// </summary>
public override float Overlap { get; set; } = 0.45f;
#endregion
#region 출력 배열 - OutputArray
/// <summary>
/// 출력 배열
/// </summary>
public override string[] OutputArray { get; set; } = new[] { "output" };
#endregion
#region 레이블 리스트 - LabelList
/// <summary>
/// 레이블 리스트
/// </summary>
public override List<YOLOLabel> LabelList { get; set; } = new List<YOLOLabel>()
{
new YOLOLabel { ID = 1, Name = "person" },
new YOLOLabel { ID = 2, Name = "bicycle" },
new YOLOLabel { ID = 3, Name = "car" },
new YOLOLabel { ID = 4, Name = "motorcycle" },
new YOLOLabel { ID = 5, Name = "airplane" },
new YOLOLabel { ID = 6, Name = "bus" },
new YOLOLabel { ID = 7, Name = "train" },
new YOLOLabel { ID = 8, Name = "truck" },
new YOLOLabel { ID = 9, Name = "boat" },
new YOLOLabel { ID = 10, Name = "traffic light" },
new YOLOLabel { ID = 11, Name = "fire hydrant" },
new YOLOLabel { ID = 12, Name = "stop sign" },
new YOLOLabel { ID = 13, Name = "parking meter" },
new YOLOLabel { ID = 14, Name = "bench" },
new YOLOLabel { ID = 15, Name = "bird" },
new YOLOLabel { ID = 16, Name = "cat" },
new YOLOLabel { ID = 17, Name = "dog" },
new YOLOLabel { ID = 18, Name = "horse" },
new YOLOLabel { ID = 19, Name = "sheep" },
new YOLOLabel { ID = 20, Name = "cow" },
new YOLOLabel { ID = 21, Name = "elephant" },
new YOLOLabel { ID = 22, Name = "bear" },
new YOLOLabel { ID = 23, Name = "zebra" },
new YOLOLabel { ID = 24, Name = "giraffe" },
new YOLOLabel { ID = 25, Name = "backpack" },
new YOLOLabel { ID = 26, Name = "umbrella" },
new YOLOLabel { ID = 27, Name = "handbag" },
new YOLOLabel { ID = 28, Name = "tie" },
new YOLOLabel { ID = 29, Name = "suitcase" },
new YOLOLabel { ID = 30, Name = "frisbee" },
new YOLOLabel { ID = 31, Name = "skis" },
new YOLOLabel { ID = 32, Name = "snowboard" },
new YOLOLabel { ID = 33, Name = "sports ball" },
new YOLOLabel { ID = 34, Name = "kite" },
new YOLOLabel { ID = 35, Name = "baseball bat" },
new YOLOLabel { ID = 36, Name = "baseball glove" },
new YOLOLabel { ID = 37, Name = "skateboard" },
new YOLOLabel { ID = 38, Name = "surfboard" },
new YOLOLabel { ID = 39, Name = "tennis racket" },
new YOLOLabel { ID = 40, Name = "bottle" },
new YOLOLabel { ID = 41, Name = "wine glass" },
new YOLOLabel { ID = 42, Name = "cup" },
new YOLOLabel { ID = 43, Name = "fork" },
new YOLOLabel { ID = 44, Name = "knife" },
new YOLOLabel { ID = 45, Name = "spoon" },
new YOLOLabel { ID = 46, Name = "bowl" },
new YOLOLabel { ID = 47, Name = "banana" },
new YOLOLabel { ID = 48, Name = "apple" },
new YOLOLabel { ID = 49, Name = "sandwich" },
new YOLOLabel { ID = 50, Name = "orange" },
new YOLOLabel { ID = 51, Name = "broccoli" },
new YOLOLabel { ID = 52, Name = "carrot" },
new YOLOLabel { ID = 53, Name = "hot dog" },
new YOLOLabel { ID = 54, Name = "pizza" },
new YOLOLabel { ID = 55, Name = "donut" },
new YOLOLabel { ID = 56, Name = "cake" },
new YOLOLabel { ID = 57, Name = "chair" },
new YOLOLabel { ID = 58, Name = "couch" },
new YOLOLabel { ID = 59, Name = "potted plant" },
new YOLOLabel { ID = 60, Name = "bed" },
new YOLOLabel { ID = 61, Name = "dining table" },
new YOLOLabel { ID = 62, Name = "toilet" },
new YOLOLabel { ID = 63, Name = "tv" },
new YOLOLabel { ID = 64, Name = "laptop" },
new YOLOLabel { ID = 65, Name = "mouse" },
new YOLOLabel { ID = 66, Name = "remote" },
new YOLOLabel { ID = 67, Name = "keyboard" },
new YOLOLabel { ID = 68, Name = "cell phone" },
new YOLOLabel { ID = 69, Name = "microwave" },
new YOLOLabel { ID = 70, Name = "oven" },
new YOLOLabel { ID = 71, Name = "toaster" },
new YOLOLabel { ID = 72, Name = "sink" },
new YOLOLabel { ID = 73, Name = "refrigerator" },
new YOLOLabel { ID = 74, Name = "book" },
new YOLOLabel { ID = 75, Name = "clock" },
new YOLOLabel { ID = 76, Name = "vase" },
new YOLOLabel { ID = 77, Name = "scissors" },
new YOLOLabel { ID = 78, Name = "teddy bear" },
new YOLOLabel { ID = 79, Name = "hair drier" },
new YOLOLabel { ID = 80, Name = "toothbrush" }
};
#endregion
#region 탐지 사용 여부 - UseDetect
/// <summary>
/// 탐지 사용 여부
/// </summary>
public override bool UseDetect { get; set; } = true;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - YOLOCOCOP6Model()
/// <summary>
/// 생성자
/// </summary>
public YOLOCOCOP6Model()
{
}
#endregion
}
}
▶ YOLOLabelKind.cs
namespace TestProject
{
/// <summary>
/// YOLO 레이블 종류
/// </summary>
public enum YOLOLabelKind
{
/// <summary>
/// 일반
/// </summary>
Generic
}
}
▶ YOLOLabel.cs
using System.Drawing;
namespace TestProject
{
/// <summary>
/// YOLO 레이블
/// </summary>
public class YOLOLabel
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region ID - ID
/// <summary>
/// ID
/// </summary>
public int ID { get; set; }
#endregion
#region 명칭 - Name
/// <summary>
/// 명칭
/// </summary>
public string Name { get; set; }
#endregion
#region 종류 - Kind
/// <summary>
/// YOLO 레이블 종류
/// </summary>
public YOLOLabelKind Kind { get; set; }
#endregion
#region 색상 - Color
/// <summary>
/// 색상
/// </summary>
public Color Color { get; set; }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - YOLOLabel()
/// <summary>
/// 생성자
/// </summary>
public YOLOLabel()
{
Color = Color.Yellow;
}
#endregion
}
}
▶ YOLOPrediction.cs
using System.Drawing;
namespace TestProject
{
/// <summary>
/// YOLO 예측
/// </summary>
public class YOLOPrediction
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 레이블 - Label
/// <summary>
/// 레이블
/// </summary>
public YOLOLabel Label { get; set; }
#endregion
#region 사각형 - Rectangle
/// <summary>
/// 사각형
/// </summary>
public RectangleF Rectangle { get; set; }
#endregion
#region 점수 - Score
/// <summary>
/// 점수
/// </summary>
public float Score { get; set; }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - YOLOPrediction()
/// <summary>
/// 생성자
/// </summary>
public YOLOPrediction()
{
}
#endregion
#region 생성자 - YOLOPrediction(label)
/// <summary>
/// 생성자
/// </summary>
/// <param name="label">레이블</param>
public YOLOPrediction(YOLOLabel label)
{
Label = label;
}
#endregion
#region 생성자 - YOLOPrediction(label, confidence)
/// <summary>
/// 생성자
/// </summary>
/// <param name="label">레이블</param>
/// <param name="confidence">신뢰도</param>
public YOLOPrediction(YOLOLabel label, float confidence) : this(label)
{
Score = confidence;
}
#endregion
}
}
▶ YOLOScorer.cs
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
namespace TestProject
{
/// <summary>
/// YOLO 채점기
/// </summary>
public class YOLOScorer<T> : IDisposable where T : YOLOModel
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 모델
/// </summary>
private readonly T model;
/// <summary>
/// 추론 세션
/// </summary>
private readonly InferenceSession inferenceSession;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - YOLOScorer()
/// <summary>
/// 생성자
/// </summary>
public YOLOScorer()
{
this.model = Activator.CreateInstance<T>();
}
#endregion
#region 생성자 - YOLOScorer(filePath, options)
/// <summary>
/// 생성자
/// </summary>
/// <param name="filePath">파일 경로</param>
/// <param name="options">옵션</param>
public YOLOScorer(string filePath, SessionOptions options = null) : this()
{
this.inferenceSession = new InferenceSession(File.ReadAllBytes(filePath), options ?? new SessionOptions());
}
#endregion
#region 생성자 - YOLOScorer(stream, options)
/// <summary>
/// 생성자
/// </summary>
/// <param name="stream">스트림</param>
/// <param name="options">옵션</param>
public YOLOScorer(Stream stream, SessionOptions options = null) : this()
{
using(BinaryReader reader = new BinaryReader(stream))
{
this.inferenceSession = new InferenceSession(reader.ReadBytes((int)stream.Length), options ?? new SessionOptions());
}
}
#endregion
#region 생성자 - YOLOScorer(weightByteArray, options)
/// <summary>
/// 생성자
/// </summary>
/// <param name="weightByteArray">가중치 바이트 배열</param>
/// <param name="options">옵션</param>
public YOLOScorer(byte[] weightByteArray, SessionOptions options = null) : this()
{
this.inferenceSession = new InferenceSession(weightByteArray, options ?? new SessionOptions());
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 예측하기 - Predict(image)
/// <summary>
/// 예측하기
/// </summary>
/// <param name="image">이미지</param>
/// <returns>예측하기</returns>
public List<YOLOPrediction> Predict(Image image)
{
return Supress(ParseOutput(Inference(image), image));
}
#endregion
#region 리소스 해제하기 - Dispose()
/// <summary>
/// 리소스 해제하기
/// </summary>
public void Dispose()
{
this.inferenceSession.Dispose();
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 크기 변경 비트맵 구하기 - GetResizeBitmap(image)
/// <summary>
/// 크기 변경 비트맵 구하기
/// </summary>
/// <param name="image">이미지</param>
/// <returns>크기 변경 비트맵</returns>
private Bitmap GetResizeBitmap(Image image)
{
PixelFormat pixelFormat = image.PixelFormat;
Bitmap bitmap = new Bitmap(this.model.Width, this.model.Height, pixelFormat);
using(Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.FromArgb(0, 0, 0, 0));
var (widthRatio, heightRatio) = (this.model.Width / (float)image.Width, this.model.Height / (float)image.Height);
float ratio = Math.Min(widthRatio, heightRatio);
var (width, height) = ((int)(image.Width * ratio), (int)(image.Height * ratio));
var (x, y) = ((this.model.Width / 2) - (width / 2), (this.model.Height / 2) - (height / 2));
graphics.DrawImage(image, new Rectangle(x, y, width, height));
}
return bitmap;
}
#endregion
#region 픽셀 추출하기 - ExtractPixels(image)
/// <summary>
/// 픽셀 추출하기
/// </summary>
/// <param name="image">이미지</param>
/// <returns>텐서</returns>
private Tensor<float> ExtractPixels(Image image)
{
Bitmap bitmap = new Bitmap(image);
Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, image.PixelFormat);
DenseTensor<float> tensor = new DenseTensor<float>(new[] { 1, 3, image.Height, image.Width });
unsafe
{
for(int y = 0; y < bitmapData.Height; y++)
{
byte* pointer = (byte*)bitmapData.Scan0 + (y * bitmapData.Stride);
for(int x = 0; x < bitmapData.Width; x++)
{
tensor[0, 0, y, x] = pointer[x * 3 + 0] / 255.0f;
tensor[0, 1, y, x] = pointer[x * 3 + 1] / 255.0f;
tensor[0, 2, y, x] = pointer[x * 3 + 2] / 255.0f;
}
}
bitmap.UnlockBits(bitmapData);
}
return tensor;
}
#endregion
#region 추론하기 - Inference(image)
/// <summary>
/// 추론하기
/// </summary>
/// <param name="image">이미지</param>
/// <returns>밀집 텐서 배열</returns>
private DenseTensor<float>[] Inference(Image image)
{
Bitmap resizedBitmap = null;
if(image.Width != this.model.Width || image.Height != this.model.Height)
{
resizedBitmap = GetResizeBitmap(image);
}
List<NamedOnnxValue> inputList = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("images", ExtractPixels(resizedBitmap ?? image))
};
IDisposableReadOnlyCollection<DisposableNamedOnnxValue> resultCollection = this.inferenceSession.Run(inputList);
List<DenseTensor<float>> outputList = new List<DenseTensor<float>>();
foreach(string output in this.model.OutputArray)
{
outputList.Add(resultCollection.First(x => x.Name == output).Value as DenseTensor<float>);
};
return outputList.ToArray();
}
#endregion
#region 탐지 파싱하기 - ParseDetect(outputTensor, image)
/// <summary>
/// 탐지 파싱하기
/// </summary>
private List<YOLOPrediction> ParseDetect(DenseTensor<float> outputTensor, Image image)
{
List<YOLOPrediction> resultList = new List<YOLOPrediction>();
var (xGain, yGain) = (this.model.Width / (float)image.Width, this.model.Height / (float)image.Height);
float gain = Math.Min(xGain, yGain);
var (xPadding, yPadding) = ((this.model.Width - image.Width * gain) / 2, (this.model.Height - image.Height * gain) / 2);
for(int i = 0; i < outputTensor.Length / this.model.Dimension; i++)
{
if(outputTensor[0, i, 4] <= this.model.Confidence)
{
continue;
}
for(int j = 5; j < this.model.Dimension; j++)
{
outputTensor[0, i, j] = outputTensor[0, i, j] * outputTensor[0, i, 4];
}
for(int k = 5; k < this.model.Dimension; k++)
{
if(outputTensor[0, i, k] <= this.model.MultipleConfidence)
{
continue;
}
float xMinimum = ((outputTensor[0, i, 0] - outputTensor[0, i, 2] / 2) - xPadding) / gain;
float yMinimum = ((outputTensor[0, i, 1] - outputTensor[0, i, 3] / 2) - yPadding) / gain;
float xMaximum = ((outputTensor[0, i, 0] + outputTensor[0, i, 2] / 2) - xPadding) / gain;
float yMaximum = ((outputTensor[0, i, 1] + outputTensor[0, i, 3] / 2) - yPadding) / gain;
xMinimum = Clamp(xMinimum, 0, image.Width );
yMinimum = Clamp(yMinimum, 0, image.Height);
xMaximum = Clamp(xMaximum, 0, image.Width );
yMaximum = Clamp(yMaximum, 0, image.Height);
YOLOLabel label = this.model.LabelList[k - 5];
YOLOPrediction prediction = new YOLOPrediction(label, outputTensor[0, i, k])
{
Rectangle = new RectangleF(xMinimum, yMinimum, xMaximum - xMinimum, yMaximum - yMinimum)
};
resultList.Add(prediction);
}
}
return resultList;
}
#endregion
#region XYXY 배열 구하기 - GetXYXYArray(sourceArray)
/// <summary>
/// XYXY 배열 구하기
/// </summary>
/// <param name="sourceArray">소스 배열</param>
/// <returns>XYXY 배열</returns>
/// <remarks>xywh bbox 형식을 xyxy로 변환한다.</remarks>
private float[] GetXYXYArray(float[] sourceArray)
{
float[] targetArray = new float[4];
targetArray[0] = sourceArray[0] - sourceArray[2] / 2f;
targetArray[1] = sourceArray[1] - sourceArray[3] / 2f;
targetArray[2] = sourceArray[0] + sourceArray[2] / 2f;
targetArray[3] = sourceArray[1] + sourceArray[3] / 2f;
return targetArray;
}
#endregion
#region 범위 내 자르기 - Clamp(value, minimumValue, maximumValue)
/// <summary>
/// 범위 내 자르기
/// </summary>
/// <param name="value">값</param>
/// <param name="minimumValue">최소값</param>
/// <param name="maximumValue">최대값</param>
/// <returns>값</returns>
public float Clamp(float value, float minimumValue, float maximumValue)
{
return (value < minimumValue) ? minimumValue : (value > maximumValue) ? maximumValue : value;
}
#endregion
#region 시그모이드 구하기 - GetSigmoid(value)
/// <summary>
/// 시그모이드 구하기
/// </summary>
/// <param name="value">값</param>
/// <returns>시그모이드</returns>
private float GetSigmoid(float value)
{
return 1 / (1 + (float)Math.Exp(-value));
}
#endregion
#region 시그모이드 파싱하기 - ParseSigmoid(outputTensor, image)
/// <summary>
/// 시그모이드 파싱하기
/// </summary>
/// <param name="outputTensor">출력 텐서</param>
/// <param name="image">이미지</param>
/// <returns>예측 리스트</returns>
private List<YOLOPrediction> ParseSigmoid(DenseTensor<float>[] outputTensor, Image image)
{
List<YOLOPrediction> resultList = new List<YOLOPrediction>();
var (xGain, yGain) = (this.model.Width / (float)image.Width, this.model.Height / (float)image.Height);
float gain = Math.Min(xGain, yGain);
var (xPadding, yPadding) = ((this.model.Width - image.Width * gain) / 2, (this.model.Height - image.Height * gain) / 2);
for(int i = 0; i < outputTensor.Length; i++)
{
int shapeCount = this.model.ShapeArray[i];
for(int j = 0; j < this.model.AnchorArray.Length; j++)
{
for(int y = 0; y < shapeCount; y++)
{
for(int x = 0; x < shapeCount; x++)
{
int offset = (shapeCount * shapeCount * j + shapeCount * y + x) * this.model.Dimension;
float[] bufferArray = outputTensor[i].Skip(offset).Take(this.model.Dimension).Select(GetSigmoid).ToArray();
float objectConfidence = bufferArray[4];
if(objectConfidence < this.model.Confidence)
{
continue;
}
List<float> scoreList = bufferArray.Skip(5).Select(b => b * objectConfidence).ToList();
float multipleConfidence = scoreList.Max();
if(multipleConfidence <= this.model.MultipleConfidence)
{
continue;
}
float rawX = (bufferArray[0] * 2 - 0.5f + x) * this.model.StrideArray[i];
float rawY = (bufferArray[1] * 2 - 0.5f + y) * this.model.StrideArray[i];
float rawWidth = (float)Math.Pow(bufferArray[2] * 2, 2) * this.model.AnchorArray[i][j][0];
float rawHeight = (float)Math.Pow(bufferArray[3] * 2, 2) * this.model.AnchorArray[i][j][1];
float[] xyxyArray = GetXYXYArray(new float[] { rawX, rawY, rawWidth, rawHeight });
float xMinimum = Clamp((xyxyArray[0] - xPadding) / gain, 0, image.Width );
float yMinimum = Clamp((xyxyArray[1] - yPadding) / gain, 0, image.Height);
float xMaximum = Clamp((xyxyArray[2] - xPadding) / gain, 0, image.Width );
float yMaximum = Clamp((xyxyArray[3] - yPadding) / gain, 0, image.Height);
YOLOLabel label = this.model.LabelList[scoreList.IndexOf(multipleConfidence)];
YOLOPrediction prediction = new YOLOPrediction(label, multipleConfidence)
{
Rectangle = new RectangleF(xMinimum, yMinimum, xMaximum - xMinimum, yMaximum - yMinimum)
};
resultList.Add(prediction);
}
}
}
}
return resultList;
}
#endregion
#region 출력 파싱하기 - ParseOutput(outputTenserArray, image)
/// <summary>
/// 출력 파싱하기
/// </summary>
/// <param name="outputTenserArray">출력 텐서 배열</param>
/// <param name="image">이미지</param>
/// <returns>예측 리스트</returns>
private List<YOLOPrediction> ParseOutput(DenseTensor<float>[] outputTenserArray, Image image)
{
return this.model.UseDetect ? ParseDetect(outputTenserArray[0], image) : ParseSigmoid(outputTenserArray, image);
}
#endregion
#region 억제하기 - Supress(sourceList)
/// <summary>
/// 억제하기
/// </summary>
/// <param name="sourceList">소스 리스트</param>
/// <returns>억제 리스트</returns>
private List<YOLOPrediction> Supress(List<YOLOPrediction> sourceList)
{
List<YOLOPrediction> targetList = new List<YOLOPrediction>(sourceList);
foreach(YOLOPrediction source in sourceList)
{
foreach(YOLOPrediction target in targetList.ToList())
{
if(target == source)
{
continue;
}
var (rectangle1, rectangle2) = (source.Rectangle, target.Rectangle);
RectangleF intersectionRectangle = RectangleF.Intersect(rectangle1, rectangle2);
float intesectionArea = intersectionRectangle.GetArea();
float unionArea = rectangle1.GetArea() + rectangle2.GetArea() - intesectionArea;
float overlap = intesectionArea / unionArea;
if(overlap > this.model.Overlap)
{
if(source.Score > target.Score)
{
targetList.Remove(target);
}
}
}
}
return targetList;
}
#endregion
}
}
▶ Program.cs
using System;
using System.Collections.Generic;
using System.Drawing;
namespace TestProject
{
/// <summary>
/// 프로그램
/// </summary>
class Program
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 프로그램 시작하기 - Main()
/// <summary>
/// 프로그램 시작하기
/// </summary>
private static void Main()
{
using Image image = Image.FromFile("IMAGE//source.jpg");
//using YOLOScorer<YOLOCOCOP5Model> scorer = new YOLOScorer<YOLOCOCOP5Model>("ASSET/yolov5s.onnx");
using YOLOScorer<YOLOCOCOP6Model> scorer = new YOLOScorer<YOLOCOCOP6Model>("ASSET/yolov5s6.onnx");
List<YOLOPrediction> predictionList = scorer.Predict(image);
using Graphics graphics = Graphics.FromImage(image);
foreach(YOLOPrediction prediction in predictionList)
{
double score = Math.Round(prediction.Score, 2);
graphics.DrawRectangles(new Pen(prediction.Label.Color, 1), new[] { prediction.Rectangle });
var (x, y) = (prediction.Rectangle.X - 3, prediction.Rectangle.Y - 23);
graphics.DrawString
(
$"{prediction.Label.Name} ({score})",
new Font("Consolas", 16, GraphicsUnit.Pixel),
new SolidBrush(prediction.Label.Color),
new PointF(x, y)
);
}
image.Save("d:\\result.jpg");
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > ML.NET' 카테고리의 다른 글
[C#/ML.NET] k-평균 클러스터링(k-means clustering) 사용하기 (0) | 2022.05.27 |
---|---|
[C#/ML.NET] 누겟 설치 : Microsoft.ML.DataView (0) | 2022.05.27 |
[C#/ML.NET] 누겟 설치 : Microsoft.ML.CpuMath (0) | 2022.05.27 |
[C#/ML.NET] 누겟 설치 : Microsoft.ML (0) | 2022.05.27 |
[C#/ML.NET/.NETCORE] 모델 빌더를 사용해 택시 요금 예측하기 (0) | 2021.09.30 |
[C#/ML.NET] 다중 클래스 분류 모델 사용하기 (0) | 2019.06.27 |
[C#/ML.NET] 이진 클래스 분류 모델 사용하기 (0) | 2019.06.27 |
[C#/ML.NET] 선형 회귀 모델 사용하기 (0) | 2019.06.26 |
댓글을 달아 주세요