본문 바로가기
📁 [4] 개발자 정보 & 코드 노트/C#

C# Windows Forms 강의 80편: 비디오 처리 및 실시간 스트리밍 - OpenCvSharp 활용

by wawManager 2025. 4. 23.

 

1. 강의 개요

이번 강의에서는 OpenCvSharp 라이브러리를 사용해 비디오 처리 및 실시간 스트리밍 애플리케이션을 제작합니다.
비디오 파일을 읽고 처리하는 방법과 웹캠을 이용한 실시간 스트리밍 구현을 실습합니다.
특히, 그레이스케일 변환, 프레임 블러링 등의 기본 비디오 필터를 적용하는 방법을 배웁니다.


2. 학습 목표

  • OpenCvSharp을 사용하여 비디오 파일 읽기 및 처리
  • 실시간 웹캠 스트리밍 구현
  • 각 프레임에 필터(그레이스케일, 블러링) 적용
  • PictureBox를 통해 비디오를 화면에 출력

3. 기능 요구사항

필수 기능

1️⃣ 비디오 파일 재생:

  • 선택한 비디오 파일을 PictureBox를 통해 재생

2️⃣ 웹캠 스트리밍:

  • 실시간으로 웹캠에서 비디오 스트리밍 출력

3️⃣ 프레임 필터 적용:

  • 비디오 프레임에 그레이스케일 변환 및 블러링 필터 적용

4️⃣ 스트리밍 종료:

  • 버튼 클릭으로 스트리밍 종료

4. 실습: 비디오 처리 및 실시간 스트리밍 애플리케이션 제작

1️⃣ 사전 준비

  1. NuGet 패키지 설치:
    • Visual Studio에서 OpenCvSharp4OpenCvSharp4.Windows 패키지를 설치합니다.
    • 설치 명령:
      Install-Package OpenCvSharp4
      Install-Package OpenCvSharp4.Windows
      
  2. 폼 구성:
    • 폼(Form) 이름: Form1
    • 컨트롤 배치:

컨트롤 타입 이름 위치 크기

Button btnOpenVideo 폼 상단 왼쪽 (100 x 30)
Button btnStartWebcam 폼 상단 중앙 (100 x 30)
Button btnStopStreaming 폼 상단 오른쪽 (100 x 30)
PictureBox pictureBox 폼 하단 전체 (500 x 400)

📌 폼 디자인 예시:

--------------------------------------------------
| [Open Video] [Start Webcam] [Stop Streaming]   |
--------------------------------------------------
|               [PictureBox - 비디오 출력]        |
--------------------------------------------------

2️⃣ 코드 작성

(1) 비디오 파일 재생

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenCvSharp;

namespace WindowsFormsApp_VideoProcessing
{
    public partial class Form1 : Form
    {
        private VideoCapture _videoCapture;
        private CancellationTokenSource _cancellationTokenSource;

        public Form1()
        {
            InitializeComponent();
        }

        // 비디오 파일 열기 및 재생
        private void btnOpenVideo_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "비디오 파일 (*.mp4;*.avi;*.mov)|*.mp4;*.avi;*.mov";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string filePath = openFileDialog.FileName;
                    PlayVideo(filePath);
                }
            }
        }

        private async void PlayVideo(string filePath)
        {
            _videoCapture = new VideoCapture(filePath);
            if (!_videoCapture.IsOpened())
            {
                MessageBox.Show("비디오 파일을 열 수 없습니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            _cancellationTokenSource = new CancellationTokenSource();
            CancellationToken token = _cancellationTokenSource.Token;

            await Task.Run(() =>
            {
                using (Mat frame = new Mat())
                {
                    while (_videoCapture.Read(frame))
                    {
                        if (token.IsCancellationRequested) break;

                        DisplayFrame(frame);
                        Cv2.WaitKey(30); // 30ms 대기
                    }
                }
            });
        }

        private void DisplayFrame(Mat frame)
        {
            if (frame.Empty()) return;

            var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(frame);
            pictureBox.Invoke(new Action(() =>
            {
                pictureBox.Image?.Dispose();
                pictureBox.Image = bitmap;
            }));
        }
    }
}

(2) 웹캠 스트리밍 구현

        // 웹캠 스트리밍 시작
        private async void btnStartWebcam_Click(object sender, EventArgs e)
        {
            _videoCapture = new VideoCapture(0); // 0번 웹캠(기본 웹캠)
            if (!_videoCapture.IsOpened())
            {
                MessageBox.Show("웹캠을 열 수 없습니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            _cancellationTokenSource = new CancellationTokenSource();
            CancellationToken token = _cancellationTokenSource.Token;

            await Task.Run(() =>
            {
                using (Mat frame = new Mat())
                {
                    while (true)
                    {
                        if (token.IsCancellationRequested) break;

                        _videoCapture.Read(frame);
                        if (frame.Empty()) continue;

                        // 그레이스케일 변환
                        Cv2.CvtColor(frame, frame, ColorConversionCodes.BGR2GRAY);

                        DisplayFrame(frame);
                        Cv2.WaitKey(1); // 1ms 대기
                    }
                }
            });
        }

(3) 스트리밍 종료

        // 스트리밍 종료
        private void btnStopStreaming_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource?.Cancel();
            _videoCapture?.Release();
            pictureBox.Image = null;
        }

(4) Designer 코드

        private void InitializeComponent()
        {
            this.btnOpenVideo = new Button();
            this.btnStartWebcam = new Button();
            this.btnStopStreaming = new Button();
            this.pictureBox = new PictureBox();

            // Open Video Button 설정
            this.btnOpenVideo.Location = new System.Drawing.Point(10, 10);
            this.btnOpenVideo.Size = new System.Drawing.Size(100, 30);
            this.btnOpenVideo.Text = "Open Video";
            this.btnOpenVideo.Click += new EventHandler(this.btnOpenVideo_Click);

            // Start Webcam Button 설정
            this.btnStartWebcam.Location = new System.Drawing.Point(120, 10);
            this.btnStartWebcam.Size = new System.Drawing.Size(100, 30);
            this.btnStartWebcam.Text = "Start Webcam";
            this.btnStartWebcam.Click += new EventHandler(this.btnStartWebcam_Click);

            // Stop Streaming Button 설정
            this.btnStopStreaming.Location = new System.Drawing.Point(230, 10);
            this.btnStopStreaming.Size = new System.Drawing.Size(100, 30);
            this.btnStopStreaming.Text = "Stop Streaming";
            this.btnStopStreaming.Click += new EventHandler(this.btnStopStreaming_Click);

            // PictureBox 설정
            this.pictureBox.Location = new System.Drawing.Point(10, 50);
            this.pictureBox.Size = new System.Drawing.Size(500, 400);
            this.pictureBox.BorderStyle = BorderStyle.FixedSingle;
            this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;

            // Form 설정
            this.ClientSize = new System.Drawing.Size(540, 480);
            this.Controls.Add(this.btnOpenVideo);
            this.Controls.Add(this.btnStartWebcam);
            this.Controls.Add(this.btnStopStreaming);
            this.Controls.Add(this.pictureBox);
            this.Text = "비디오 처리 및 스트리밍";
        }

3️⃣ 실행 결과

1️⃣ 비디오 파일 재생

  • "Open Video" 버튼 클릭 → 파일 선택 → PictureBox에 비디오 프레임 재생

2️⃣ 웹캠 스트리밍

  • "Start Webcam" 버튼 클릭 → 실시간으로 웹캠 비디오 출력

3️⃣ 그레이스케일 변환

  • 웹캠 프레임을 흑백으로 변환하여 출력

4️⃣ 스트리밍 종료

  • "Stop Streaming" 버튼 클릭 → 스트리밍 종료

5. 주요 개념 요약

  • OpenCvSharp: 비디오 파일 및 웹캠 처리를 위한 라이브러리
  • VideoCapture: 비디오 파일 또는 웹캠 데이터를 캡처하는 클래스
  • CancellationToken: 비동기 작업 취소를 위한 토큰
  • Mat: OpenCvSharp에서 이미지 데이터를 저장하는 클래스

 

 

📌 #CSharp #WindowsForms #OpenCvSharp #비디오처리 #웹캠스트리밍 #실시간처리