■ 텐서플로우를 사용해 물체 인식하기

----------------------------------------------------------------------------------------------------


TestProject.zip TestProject.z01 TestProject.z02 TestProject.z03 TestProject.z04 TestProject.z05 TestProject.z06 TestProject.z07 TestProject.z08 TestProject.z09 TestProject.z10 TestProject.z11 TestProject.z12 TestProject.z13 TestProject.z14


MainForm.cs

 

 

using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.IO;

using System.Windows.Forms;

 

using AForge.Video;

using AForge.Video.DirectShow;

 

using TensorFlow;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 디스플레이 레이블 그래픽스

        /// </summary>

        private Graphics displayLabelGraphics = null;

 

        /// <summary>

        /// 필터 정보 컬렉션

        /// </summary>

        private FilterInfoCollection filterInfoCollection = null;

 

        /// <summary>

        /// 비디오 캡처 장치

        /// </summary>

        private VideoCaptureDevice videoCaptureDevice = null;

 

 

        /// <summary>

        /// 모델 배열

        /// </summary>

        private byte[] modelArray = null;

 

        /// <summary>

        /// 레이블 배열

        /// </summary>

        private string[] labelArray = null;

 

 

        /// <summary>

        /// 텐서플로우 그래프

        /// </summary>

        private TFGraph graph = null;

 

        /// <summary>

        /// 텐서플로우 세션

        /// </summary>

        private TFSession session = null;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region MainForm

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            Load                   += Form_Load;

            FormClosing            += Form_FormClosing;

            this.startButton.Click += startButton_Click;

 

            #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)

        {

            this.displayLabelGraphics = this.displayLabel.CreateGraphics();

 

            #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\\frozen_process_no_filter_tiny.pb");

 

            #endregion

            #region 레이블 배열을 설정한다.

 

            this.labelArray = File.ReadAllLines("DATA\\yolo_labels.txt");

 

            #endregion

            #region 텐서플로우 그래프를 설정한다.

 

            this.graph = new TFGraph();

 

            this.graph.Import(this.modelArray, "");

 

            #endregion

            #region 텐서플로우 세션을 설정한다.

 

            this.session = new TFSession(graph);

 

            #endregion

 

            Bitmap bitmap = new Bitmap(100, 100, PixelFormat.Format24bppRgb);

 

            Predict(bitmap);

        }

 

        #endregion

        #region 폼 닫을 경우 처리하기 - Form_FormClosing(sender, e)

 

        /// <summary>

        /// 폼 닫을 경우 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_FormClosing(object sender, FormClosingEventArgs e)

        {

            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();

            }

            else

            {

                StopCameraCaoture();

 

                this.startButton.Text = "시작";

            }

        }

 

        #endregion

        #region 비디오 캡처 장치 신규 프레임 처리하기 - videoCaptureDevice_NewFrame(sender, e)

 

        /// <summary>

        /// 비디오 캡처 장치 신규 프레임 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void videoCaptureDevice_NewFrame(object sender, NewFrameEventArgs e)

        {

            Bitmap bitmap = e.Frame;

 

            TFTensor[] outputTensorArray = Predict(bitmap);

 

            float[,] rectangleArray   = (float[,])outputTensorArray[0].GetValue();

            float[]  probabilityArray = (float[] )outputTensorArray[1].GetValue();

            long[]   labelIndexArray  = (long[]  )outputTensorArray[2].GetValue();

 

            using(Graphics graphics = Graphics.FromImage(bitmap))

            {

                for(int i = 0; i < probabilityArray.Length; i++)

                {

                    if(probabilityArray[i] > 0.2)

                    {

                        int rectangleLeft   = (int)(rectangleArray[i, 0] * (float)bitmap.Width );

                        int rectangleTop    = (int)(rectangleArray[i, 1] * (float)bitmap.Height);

                        int rectangleWidth  = (int)(rectangleArray[i, 2] * (float)bitmap.Width );

                        int rectangleHeight = (int)(rectangleArray[i, 3] * (float)bitmap.Height);

 

                        graphics.DrawRectangle

                        (

                            new Pen(Color.Red, 2),

                            rectangleLeft - rectangleWidth  / 2,

                            rectangleTop  - rectangleHeight / 2,

                            rectangleWidth,

                            rectangleHeight

                        );

 

                        string label = this.labelArray[labelIndexArray[i]] + " " + probabilityArray[i].ToString();

 

                        graphics.DrawString

                        (

                            label,

                            Font,

                            Brushes.Red,

                            rectangleLeft - rectangleWidth  / 2,

                            rectangleTop  - rectangleHeight / 2

                        );

                    }

                }

            }

 

            this.displayLabelGraphics.DrawImage(bitmap, 0, 0, this.displayLabel.Width, this.displayLabel.Height);

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 카메라 캡처 시작하기 - StartCameraCapture()

 

        /// <summary>

        /// 카메라 캡처 시작하기

        /// </summary>

        private void StartCameraCapture()

        {

            if(this.videoCaptureDevice == null || !this.videoCaptureDevice.IsRunning)

            {

                FilterInfo filterInfo = this.filterInfoCollection[this.cameraDeviceComboBox.SelectedIndex];

 

                this.videoCaptureDevice = new VideoCaptureDevice(filterInfo.MonikerString);

 

                this.videoCaptureDevice.NewFrame += videoCaptureDevice_NewFrame;

 

                this.videoCaptureDevice.Start();

            }

        }

 

        #endregion

        #region 카메라 캡처 중단하기 - StopCameraCaoture()

 

        /// <summary>

        /// 카메라 캡처 중단하기

        /// </summary>

        private void StopCameraCaoture()

        {

            if(this.videoCaptureDevice != null && this.videoCaptureDevice.IsRunning)

            {

                this.videoCaptureDevice.NewFrame -= videoCaptureDevice_NewFrame;

 

                this.videoCaptureDevice.SignalToStop();

 

                this.videoCaptureDevice.WaitForStop();

 

                this.videoCaptureDevice = null;

            }

        }

 

        #endregion

 

        #region 텐서 구하기 - GetTensor(sourceArray)

 

        /// <summary>

        /// 텐서 구하기

        /// </summary>

        /// <param name="sourceArray">소스 배열</param>

        /// <returns>텐서</returns>

        private TFTensor GetTensor(byte[] sourceArray)

        {

            TFGraph  graph  = new TFGraph();

            TFOutput input  = graph.Placeholder(TFDataType.String);

            TFOutput output = graph.Cast(graph.DecodeJpeg(contents : input, channels : 3), DstT : TFDataType.Float);

            TFTensor tensor = TFTensor.CreateString(sourceArray);

 

            using(TFSession session = new TFSession(graph))

            {

                TFTensor[] normalizedTensorArray = session.Run

                (

                    inputs      : new[] { input  },

                    outputs     : new[] { output },

                    inputValues : new[] { tensor }

                );

 

                return normalizedTensorArray[0];

            }

        }

 

        #endregion

        #region 예측하기 - Predict(bitmap)

 

        /// <summary>

        /// 예측하기

        /// </summary>

        /// <param name="bitmap">비트맵</param>

        /// <returns>결과 텐서 배열</returns>

        private TFTensor[] Predict(Bitmap bitmap)

        {

            MemoryStream memoryStream = new MemoryStream();

 

            bitmap.Save(memoryStream, ImageFormat.Jpeg);

 

            TFTensor tensor = GetTensor(memoryStream.GetBuffer());

 

            TFSession.Runner runner = this.session.GetRunner();

 

            runner.AddInput(this.graph["input"][0], tensor).Fetch("boxes", "classes_prob", "classes_arg");

 

            TFTensor[] outputTensorArray = runner.Run();

 

            return outputTensorArray;

        }

 

        #endregion

    }

}

 

----------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요