๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿš€ Development/C#

C#๊ณผ .NET์œผ๋กœ ์›น์บ  ์ดฌ์˜ ๋ฐ ์ €์žฅ ์˜ˆ์ œ

by Jay Din 2024. 11. 12.
728x90
๋ฐ˜์‘ํ˜•

1. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

AForge ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‹ค์šด๋กœ๋“œ

 

  1. Visual Studio์—์„œ Windows Forms App (.NET Framework) ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  2. NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•ด AForge.Video์™€ AForge.Video.DirectShow ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
    • AForge.Video๋Š” ๊ธฐ๋ณธ ๋น„๋””์˜ค ๊ด€๋ จ ์ž‘์—…์„ ์ง€์›ํ•˜๊ณ ,
    • AForge.Video.DirectShow๋Š” ์›น์บ ๊ณผ ๊ฐ™์€ ๋น„๋””์˜ค ์žฅ์น˜์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  3. AForge ์„ค์น˜ ๋ฐฉ๋ฒ•
    • ๋„๊ตฌ > NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž > ์†”๋ฃจ์…˜์šฉ NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ ๋ฉ”๋‰ด๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
    • AForge.Video์™€ AForge.Video.DirectShow๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

 

2. UI ๊ตฌ์„ฑ ๋ฐ ์ฝ”๋“œ ์ž‘์„ฑ

์›น์บ  ์บก์ณ ์•ฑ

 

  1. Form ๋””์ž์ธ ์ฐฝ์—์„œPictureBox์™€ Button์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • PictureBox๋Š” ์›น์บ ์˜ ์‹ค์‹œ๊ฐ„ ๋น„๋””์˜ค๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    • Button์€ ์‚ฌ์ง„์„ ์บก์ฒ˜ํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  2. ๊ฐ ์ปจํŠธ๋กค์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.
    • PictureBox ์ด๋ฆ„์„ pictureBox1๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • Button ์ด๋ฆ„์„ captureButton์œผ๋กœ, ํ…์ŠคํŠธ๋Š” "Capture"๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  3. UI ๊ตฌ์„ฑ ์ฝ”๋“œ๋ฅผ Form1.Designer.cs ํŒŒ์ผ์— ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์„œ๋Š” PictureBox์™€ Button์„ ์ถ”๊ฐ€ํ•˜๊ณ , ์œ„์น˜์™€ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
namespace WebcamCaptureApp
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
        private System.Windows.Forms.PictureBox pictureBox1;
        private System.Windows.Forms.Button captureButton;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.captureButton = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.SuspendLayout();
            
            // 
            // pictureBox1
            // 
            this.pictureBox1.Location = new System.Drawing.Point(12, 12);
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.Size = new System.Drawing.Size(640, 480); // Width: 640, Height: 480
            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.pictureBox1.TabIndex = 0;
            this.pictureBox1.TabStop = false;
            
            // 
            // captureButton
            // 
            this.captureButton.Location = new System.Drawing.Point(280, 500); // Centered below the picture box
            this.captureButton.Name = "captureButton";
            this.captureButton.Size = new System.Drawing.Size(100, 40);
            this.captureButton.TabIndex = 1;
            this.captureButton.Text = "Capture";
            this.captureButton.UseVisualStyleBackColor = true;
            this.captureButton.Click += new System.EventHandler(this.captureButton_Click);
            
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(664, 561); // Form width and height
            this.Controls.Add(this.captureButton);
            this.Controls.Add(this.pictureBox1);
            this.Name = "Form1";
            this.Text = "Webcam Capture App";
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.ResumeLayout(false);
        }
    }
}

 

3. ๊ธฐ๋Šฅ ๋กœ์ง ์ฝ”๋“œ ์ž‘์„ฑ

๋‹ค์Œ ์ฝ”๋“œ๋ฅผ Form1.cs ํŒŒ์ผ์— ์ž‘์„ฑํ•˜์—ฌ ์›น์บ ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  ๋กœ์ปฌ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;

namespace WebcamCaptureApp
{
    public partial class Form1 : Form
    {
        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource;

        public Form1()
        {
            InitializeComponent();
            Load += Form1_Load;
            FormClosing += Form1_FormClosing;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ๋น„๋””์˜ค ์žฅ์น˜(์›น์บ ) ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

            if (videoDevices.Count == 0)
            {
                MessageBox.Show("์›น์บ ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
                return;
            }

            // ์ฒซ ๋ฒˆ์งธ ์›น์บ  ์„ ํƒ
            videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
            videoSource.NewFrame += new NewFrameEventHandler(VideoSource_NewFrame);
            videoSource.Start();
        }

        private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            // PictureBox์— ํ˜„์žฌ ํ”„๋ ˆ์ž„ ํ‘œ์‹œ
            Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone();
            pictureBox1.Image = bitmap;
        }

        private void captureButton_Click(object sender, EventArgs e)
        {
            // PictureBox์˜ ํ˜„์žฌ ์ด๋ฏธ์ง€๋ฅผ ์บก์ฒ˜ํ•˜์—ฌ ์ €์žฅ
            if (pictureBox1.Image != null)
            {
                string directoryPath = @"C:\Images";
                Directory.CreateDirectory(directoryPath);

                string filePath = Path.Combine(directoryPath, $"capture_{DateTime.Now:yyyyMMdd_HHmmss}.jpg");
                pictureBox1.Image.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);

                MessageBox.Show($"์ด๋ฏธ์ง€๊ฐ€ {filePath}์— ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // ํผ ์ข…๋ฃŒ ์‹œ ์นด๋ฉ”๋ผ ์ŠคํŠธ๋ฆผ ์ •์ง€ ๋ฐ ํ•ด์ œ
            if (videoSource != null && videoSource.IsRunning)
            {
                videoSource.SignalToStop();
                videoSource.WaitForStop();
            }
        }
    }
}

 

  • Form1_Load
    • ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ์›น์บ  ์žฅ์น˜ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฒซ ๋ฒˆ์งธ ์›น์บ  ์žฅ์น˜๋ฅผ videoSource๋กœ ์„ค์ •ํ•˜๊ณ , ์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค VideoSource_NewFrame ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • VideoSource_NewFrame
    • ์›น์บ ์˜ ์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์„ PictureBox์— ํ‘œ์‹œํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • captureButton_Click
    • ํ˜„์žฌ PictureBox์˜ ์ด๋ฏธ์ง€๋ฅผ ์บก์ฒ˜ํ•˜์—ฌ C:\Images ํด๋”์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
    • ์ €์žฅ ํŒŒ์ผ์˜ ์ด๋ฆ„์€ ํ˜„์žฌ ์‹œ๊ฐ„(yyyyMMdd_HHmmss ํ˜•์‹)์„ ์‚ฌ์šฉํ•ด ์œ ๋‹ˆํฌํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • Form1_FormClosing
    • ํผ์ด ๋‹ซํž ๋•Œ ์›น์บ  ์ŠคํŠธ๋ฆผ์„ ์ •์ง€ํ•˜์—ฌ ์ž์›์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

 

4. ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ๋ฐ ํ…Œ์ŠคํŠธ

  1. ํ”„๋กœ์ ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์›น์บ ์—์„œ ๋น„๋””์˜ค ์ŠคํŠธ๋ฆผ์ด PictureBox์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  2. Capture ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ˜„์žฌ ํ™”๋ฉด์„ ์บก์ฒ˜ํ•˜์—ฌ C:\Images์— JPEG ํŒŒ์ผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

์›น์บ ์œผ๋กœ ์‚ฌ์ง„ ์ดฌ์˜

์›น์บก ์‚ฌ์ง„ ์ดฌ์˜

 

์ง€์ • ๊ฒฝ๋กœ์— ์ €์žฅ๋œ ์‚ฌ์ง„

์ง€์ • ๊ฒฝ๋กœ์— ์ €์žฅ

 

์ €์žฅ๋œ ์‚ฌ์ง„ ํ™•์ธ

์ €์žฅ๋œ ์‚ฌ์ง„ ํ™•์ธ

 

728x90
๋ฐ˜์‘ํ˜•