■ YOLO 이미지 객체 인식하기

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


TestSolution.zip TestSolution.z01 TestSolution.z02 TestSolution.z03 TestSolution.z04 TestSolution.z05 TestSolution.z06 TestSolution.z07 TestSolution.z08


[TestProject 프로젝트]

 

MainForm.cs

 

 

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Drawing;

using System.IO;

using System.Linq;

using System.Threading.Tasks;

using System.Windows.Forms;

 

using TestCommon;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

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

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

 

        #region Field

 

        /// <summary>

        /// YOLO 레퍼

        /// </summary>

        private YoloWrapper wrapper;

 

        #endregion

 

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            this.processImageButton.Enabled = false;

 

            this.sourceDataGridView.AutoGenerateColumns = false;

            this.resultDataGridView.AutoGenerateColumns = false;

 

            IEnumerable<ImageInfo> imageInfoEnumerable = new DirectoryImageReader().Analyze(@".\IMAGE");

 

            this.sourceDataGridView.DataSource = imageInfoEnumerable.ToList();

 

            ConfigurationDetector configurationDetector = new ConfigurationDetector();

 

            YoloConfiguration configuration = configurationDetector.Detect();

 

            if(configuration == null)

            {

                MessageBox.Show("YOLO 구성 탐지를 실패했습니다.", "INFORMATION", MessageBoxButtons.OK, MessageBoxIcon.Information);

 

                return;

            }

 

            this.toolStripStatusLabel1.Text = string.Empty;

            this.toolStripStatusLabel2.Text = string.Empty;

 

            FormClosing += Form_FormClosing;

            this.sourceDataGridView.SelectionChanged += sourceDataGridView_SelectionChanged;

            this.sourceDataGridView.KeyDown          += sourceDataGridView_KeyDown;

            this.processImageButton.Click            += processImageButton_Click;

            this.resultDataGridView.SelectionChanged += resultDataGridView_SelectionChanged;

 

            Task.Run(() => Initialize(configuration));

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

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

        //////////////////////////////////////////////////////////////////////////////// Event

 

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

 

        /// <summary>

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

        /// </summary>

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

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

        private void Form_FormClosing(object sender, FormClosingEventArgs e)

        {

            this.wrapper.Dispose();

        }

 

        #endregion

        #region 소스 데이터 그리드 뷰 선택 변경시 처리하기 - sourceDataGridView_SelectionChanged(sender, e)

 

        /// <summary>

        /// 소스 데이터 그리드 뷰 선택 변경시 처리하기

        /// </summary>

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

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

        private void sourceDataGridView_SelectionChanged(object sender, EventArgs e)

        {

            Image previousImage = this.pictureBox.Image;

 

            ImageInfo imageInfo = GetCurrentImageInfo();

 

            this.pictureBox.Image = Image.FromFile(imageInfo.FilePath);

 

            previousImage?.Dispose();

 

            this.resultDataGridView.DataSource = null;

        }

 

        #endregion

        #region 소스 데이터 그리드 뷰 키 DOWN 처리하기 - sourceDataGridView_KeyDown(sender, e)

 

        /// <summary>

        /// 소스 데이터 그리드 뷰 키 DOWN 처리하기

        /// </summary>

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

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

        private void sourceDataGridView_KeyDown(object sender, KeyEventArgs e)

        {

            if(e.KeyCode == Keys.Space)

            {

                Detect();

            }

        }

 

        #endregion

        #region 이미지 처리 버튼 클릭시 처리하기 - processImageButton_Click(sender, e)

 

        /// <summary>

        /// 이미지 처리 버튼 클릭시 처리하기

        /// </summary>

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

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

        private void processImageButton_Click(object sender, EventArgs e)

        {

            Detect();

        }

 

        #endregion

        #region 결과 데이터 그리드 뷰 선택 변경시 처리하기 - resultDataGridView_SelectionChanged(sender, e)

 

        /// <summary>

        /// 결과 데이터 그리드 뷰 선택 변경시 처리하기

        /// </summary>

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

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

        private void resultDataGridView_SelectionChanged(object sender, EventArgs e)

        {

            if(!this.resultDataGridView.Focused)

            {

                return;

            }

 

            List<YoloItem> itemList = this.resultDataGridView.DataSource as List<YoloItem>;

 

            YoloItem item = this.resultDataGridView.CurrentRow?.DataBoundItem as YoloItem;

 

            DrawImage(itemList, item);

        }

 

        #endregion

        #region 폴더 열기 메뉴 항목 클릭시 처리하기 - openFolderMenuItem_Click(sender, e)

 

        /// <summary>

        /// 폴더 열기 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void openFolderMenuItem_Click(object sender, EventArgs e)

        {

            DialogResult result = this.folderBrowserDialog.ShowDialog();

 

            if(result != DialogResult.OK)

            {

                return;

            }

            

            IEnumerable<ImageInfo> imageInfoEnumerable = new DirectoryImageReader().Analyze(this.folderBrowserDialog.SelectedPath);

 

            this.sourceDataGridView.DataSource = imageInfoEnumerable.ToList();

        }

 

        #endregion

 

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

 

        #region 초기화 하기 - Initialize(configuration)

 

        /// <summary>

        /// 초기화 하기

        /// </summary>

        /// <param name="configuration">YOLO 구성</param>

        private void Initialize(YoloConfiguration configuration)

        {

            Stopwatch stopwatch = new Stopwatch();

 

            stopwatch.Start();

 

            this.wrapper = new YoloWrapper(configuration.ConfigurationFilePath, configuration.WeightFilePath, configuration.NameFilePath, 0);

 

            stopwatch.Stop();

 

            this.statusStrip.Invoke

            (

                new MethodInvoker

                (

                    delegate()

                    {

                        this.toolStripStatusLabel1.Text = string.Format

                        (

                            "초기화 시간 : {0} 밀리초, 탐지 시스템 : {1} ({2})",

                            stopwatch.Elapsed.TotalMilliseconds,

                            this.wrapper.DetectionSystemType,

                            this.wrapper.EnvironmentReport.GraphicDeviceName

                        );

                    }

                )

            );

 

            this.processImageButton.Invoke(new MethodInvoker(delegate () { this.processImageButton.Enabled = true; }));

        }

 

        #endregion

        #region 현재 이미지 정보 구하기 - GetCurrentImageInfo()

 

        /// <summary>

        /// 현재 이미지 정보 구하기

        /// </summary>

        /// <returns>현재 이미지 정보</returns>

        private ImageInfo GetCurrentImageInfo()

        {

            ImageInfo imageInfo = this.sourceDataGridView.CurrentRow?.DataBoundItem as ImageInfo;

 

            return imageInfo;

        }

 

        #endregion

        #region 펜 구하기 - GetPen(confidence, width)

 

        /// <summary>

        /// 펜 구하기

        /// </summary>

        /// <param name="confidence">확신도</param>

        /// <param name="width">너비</param>

        /// <returns></returns>

        private Pen GetPen(double confidence, int width)

        {

            int size = width / 100;

 

            if(confidence > 0.5)

            {

                return new Pen(Brushes.GreenYellow, size);

            }

            else if(confidence > 0.2 && confidence <= 0.5)

            {

                return new Pen(Brushes.Orange, size);

            }

 

            return new Pen(Brushes.DarkRed, size);

        }

 

        #endregion

        #region 이미지 그리기 - DrawImage(itemList, selectedItem)

 

        /// <summary>

        /// 이미지 그리기

        /// </summary>

        /// <param name="itemList">이미지 리스트</param>

        /// <param name="selectedItem">선택 이미지</param>

        private void DrawImage(List<YoloItem> itemList, YoloItem selectedItem = null)

        {

            ImageInfo imageInfo = GetCurrentImageInfo();

 

            Image image = Image.FromFile(imageInfo.FilePath);

 

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

            {

                foreach(YoloItem item in itemList)

                {

                    int x      = item.X;

                    int y      = item.Y;

                    int width  = item.Width;

                    int height = item.Height;

 

                    using(SolidBrush overlayBrush = new SolidBrush(Color.FromArgb(150, 255, 255, 102)))

                    {

                        using(Pen pen = GetPen(item.Confidence, image.Width))

                        {

                            if(item.Equals(selectedItem))

                            {

                                graphics.FillRectangle(overlayBrush, x, y, width, height);

                            }

 

                            graphics.DrawRectangle(pen, x, y, width, height);

 

                            graphics.Flush();

                        }

                    }

                }

            }

 

            Image previousImage = this.pictureBox.Image;

 

            this.pictureBox.Image = image;

 

            previousImage?.Dispose();

        }

 

        #endregion

        #region 탐지하기 - Detect()

 

        /// <summary>

        /// 탐지하기

        /// </summary>

        private void Detect()

        {

            if(this.wrapper == null)

            {

                return;

            }

 

            bool memoryTransfer = true;

 

            ImageInfo imageInfo = GetCurrentImageInfo();

 

            byte[] imageByteArray = File.ReadAllBytes(imageInfo.FilePath);

 

            Stopwatch stopwatch = new Stopwatch();

 

            stopwatch.Start();

 

            List<YoloItem> itemList;

 

            if(memoryTransfer)

            {

                itemList = this.wrapper.Detect(imageByteArray).ToList();

            }

            else

            {

                itemList = this.wrapper.Detect(imageInfo.FilePath).ToList();

            }

 

            stopwatch.Stop();

 

            this.toolStripStatusLabel2.Text = $"이미지 처리 시간 : {stopwatch.Elapsed.TotalMilliseconds:0.00} 밀리초";

 

            this.resultDataGridView.DataSource = itemList;

 

            DrawImage(itemList);

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요