728x90
반응형
728x170
TestProject.zip
다운로드
TestProject.z01
다운로드
TestProject.z02
다운로드
TestProject.z03
다운로드
TestProject.z04
다운로드
TestProject.z05
다운로드
TestProject.z06
다운로드
▶ MainForm.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using TensorFlow;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 타이머
/// </summary>
private Timer timer = null;
/// <summary>
/// 필터 정보 컬렉션
/// </summary>
private FilterInfoCollection filterInfoCollection = null;
/// <summary>
/// 모델 배열
/// </summary>
private byte[] modelArray;
/// <summary>
/// 레이블 배열
/// </summary>
private string[] labelArray = null;
/// <summary>
/// 텐서플로우 세션
/// </summary>
private TFSession session = null;
/// <summary>
/// 텐서플로우 그래프
/// </summary>
private TFGraph graph = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
#region 타이머를 설정한다.
this.timer = new Timer();
this.timer.Interval = 1000;
#endregion
#region 이벤트를 설정한다.
Load += Form_Load;
FormClosing += Form_FormClosing;
this.startButton.Click += startButton_Click;
this.timer.Tick += timer_Tick;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
#region 카메라 장치 콤보 박스를 설정한다.
this.filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
for(int i = 0; i < this.filterInfoCollection.Count; i++)
{
this.cameraDeviceComboBox.Items.Add(this.filterInfoCollection[i].Name);
}
if(this.cameraDeviceComboBox.Items.Count > 0)
{
this.cameraDeviceComboBox.SelectedIndex = 0;
}
#endregion
#region 시작 버튼을 설정한다.
this.startButton.Enabled = (this.cameraDeviceComboBox.Items.Count > 0);
#endregion
#region 모델 배열을 설정한다.
this.modelArray = File.ReadAllBytes("DATA\\tensorflow_inception_graph.pb");
#endregion
#region 레이블 배열을 설정한다.
this.labelArray = File.ReadAllLines("DATA\\imagenet_comp_graph_label_strings.txt");
#endregion
this.graph = new TFGraph();
this.session = new TFSession(graph);
this.graph.Import(this.modelArray, "");
}
#endregion
#region 폼 닫을 경우 처리하기 - Form_FormClosing(sender, e)
/// <summary>
/// 폼 닫을 경우 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
this.timer.Stop();
StopCameraCaoture();
}
#endregion
#region 시작 버튼 클릭시 처리하기 - startButton_Click(sender, e)
/// <summary>
/// 시작 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void startButton_Click(object sender, EventArgs e)
{
if(this.startButton.Text == "시작")
{
this.startButton.Text = "중지";
StartCameraCapture();
this.timer.Start();
}
else
{
this.timer.Stop();
StopCameraCaoture();
this.startButton.Text = "시작";
}
}
#endregion
#region 타이머 틱 처리하기 - timer_Tick(sender, e)
/// <summary>
/// 타이머 틱 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void timer_Tick(object sender, EventArgs e)
{
Bitmap bitmap = this.videoSourcePlayer.GetCurrentVideoFrame();
if(bitmap == null)
{
return;
}
MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Jpeg);
TFTensor tensor = GetTensor(memoryStream.GetBuffer());
TFSession.Runner runner = this.session.GetRunner();
runner.AddInput(graph["input"][0], tensor).Fetch(graph["output"][0]);
TFTensor[] outputTensorArray = runner.Run();
TFTensor outputTensor = outputTensorArray[0];
long[] shapeArray = outputTensor.Shape;
if(outputTensor.NumDims != 2 || shapeArray[0] != 1)
{
string shapeString = string.Empty;
foreach(long shape in shapeArray)
{
shapeString += $"{shape} ";
}
shapeString = shapeString.Trim();
Console.WriteLine($"에러 : [1 N] 차원 텐서의 생성을 기대했는데(여기서 N은 라벨의 개수), [{shapeString}] 차원 텐서를 생성했습니다.");
Environment.Exit(1);
}
bool jagged = true;
int bestIndex = 0;
float best = 0;
if(jagged)
{
float[] probabilityArray = ((float[][])outputTensor.GetValue(jagged : true))[0];
for(int i = 0; i < probabilityArray.Length; i++)
{
if(probabilityArray[i] > best)
{
bestIndex = i;
best = probabilityArray[i];
}
}
}
else
{
float[,] valueArray = (float[,])outputTensor.GetValue(jagged : false);
for(int i = 0; i < valueArray.GetLength(1); i++)
{
if(valueArray[0, i] > best)
{
bestIndex = i;
best = valueArray[0, i];
}
}
}
this.informationLabel.Text = $"판정 : [{bestIndex}] {best * 100.0}% {this.labelArray[bestIndex]}";
Console.WriteLine($"판정 : [{bestIndex}] {best * 100.0}% {this.labelArray[bestIndex]}");
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 카메라 캡처 시작하기 - StartCameraCapture()
/// <summary>
/// 카메라 캡처 시작하기
/// </summary>
private void StartCameraCapture()
{
FilterInfo filterInfo;
filterInfo = this.filterInfoCollection[this.cameraDeviceComboBox.SelectedIndex];
VideoCaptureDevice videoCaptureDevice = new VideoCaptureDevice(filterInfo.MonikerString);
this.videoSourcePlayer.VideoSource = videoCaptureDevice;
this.videoSourcePlayer.AutoSizeControl = true;
this.videoSourcePlayer.Start();
}
#endregion
#region 카메라 캡처 중단하기 - StopCameraCaoture()
/// <summary>
/// 카메라 캡처 중단하기
/// </summary>
private void StopCameraCaoture()
{
this.videoSourcePlayer.SignalToStop();
this.videoSourcePlayer.WaitForStop();
}
#endregion
#region 값 설정하기 - SetValue(graph, input, output)
/// <summary>
/// 값 설정하기
/// </summary>
/// <param name="graph">그래프</param>
/// <param name="input">입력</param>
/// <param name="output">출력</param>
private void SetValue(out TFGraph graph, out TFOutput input, out TFOutput output)
{
const int IMAGE_WIDTH = 224;
const int IMAGE_HEIGHT = 224;
const float MEAN = 117;
const float SCALE = 1;
graph = new TFGraph();
input = graph.Placeholder(TFDataType.String);
output = graph.Div
(
x : graph.Sub
(
x : graph.ResizeBilinear
(
images : graph.ExpandDims
(
input : graph.Cast
(
graph.DecodeJpeg(contents : input, channels : 3),
DstT : TFDataType.Float
),
dim : graph.Const(0, "make_batch")
),
size : graph.Const(new int[] { IMAGE_WIDTH, IMAGE_HEIGHT }, "size")),
y : graph.Const(MEAN, "mean")
),
y : graph.Const(SCALE, "scale")
);
}
#endregion
#region 텐서 구하기 - GetTensor(sourceArray)
/// <summary>
/// 텐서 구하기
/// </summary>
/// <param name="sourceArray">소스 배열</param>
/// <returns>텐서</returns>
private TFTensor GetTensor(byte[] sourceArray)
{
TFTensor tensor = TFTensor.CreateString(sourceArray);
TFGraph graph;
TFOutput input;
TFOutput output;
SetValue(out graph, out input, out output);
using(TFSession session = new TFSession(graph))
{
TFTensor[] normalizedTensorArray = session.Run
(
inputs : new[] { input },
inputValues : new[] { tensor },
outputs : new[] { output }
);
return normalizedTensorArray[0];
}
}
#endregion
}
}
※ 닷넷 프레임워크 4.7.1 버전을 사용해야 한다.
※ 프로젝트 속성의 빌드 탭에서 "32비트 기본 사용"을 체크 해제해야 한다.
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] 유사 이미지 찾기 (0) | 2018.09.20 |
---|---|
[C#/WINFORM] 텐서플로우를 사용해 물체 인식하기 (0) | 2018.09.01 |
[C#/WINFORM] Cursor 클래스 : 이미지 커서 구하기 (0) | 2018.09.01 |
[C#/WINFORM] DataGridView 클래스 : RowPostPaint 이벤트를 사용해 행 번호 표시하기 (0) | 2018.09.01 |
[C#/WINFORM] DataGridView 클래스 : 마우스를 사용해 항목 순서 변경하기 (0) | 2018.09.01 |
[C#/WINFORM] Control 클래스 : ProcessCmdKey 메소드를 사용해 COPY/PASTE/CUT 방지하기 (0) | 2018.08.15 |
[C#/WINFORM] TextBox 클래스 : ShortcustsEnabled 속성을 사용해 COPY/PASTE/CUT 방지하기 (0) | 2018.08.15 |
[C#/WINFORM] Control 클래스 : WndProc 메소드를 사용해 COPY/PASTE/CUT 방지하기 (0) | 2018.08.15 |
[C#/WINFORM] 색상 맵 사용하기 (0) | 2018.04.14 |
[C#/WINFORM] 별 그리기 (0) | 2018.04.14 |
댓글을 달아 주세요