Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 5개 있습니다.)
(시리즈 글이 10개 있습니다.)
.NET Framework: 707. OpenCV 응용 프로그램을 C#으로 구현 - OpenCvSharp
; https://www.sysnet.pe.kr/2/0/11402

.NET Framework: 708. C# - OpenCvSharp을 이용한 동영상(avi, mp4, ...) 처리
; https://www.sysnet.pe.kr/2/0/11403

.NET Framework: 709. C# - OpenCvSharp을 이용한 동영상(avi, mp4, ...) 처리 + Direct2D
; https://www.sysnet.pe.kr/2/0/11404

.NET Framework: 710. C# - OpenCvSharp을 이용한 Webcam 영상 처리 + Direct2D
; https://www.sysnet.pe.kr/2/0/11405

.NET Framework: 711. C# - OpenCvSharp의 Mat 데이터 조작 방법
; https://www.sysnet.pe.kr/2/0/11406

.NET Framework: 723. C# - OpenCvSharp 사용 시 C/C++을 이용한 속도 향상 (for 루프 연산)
; https://www.sysnet.pe.kr/2/0/11422

VC++: 123. 내가 만든 코드보다 OpenCV의 속도가 월등히 빠른 이유
; https://www.sysnet.pe.kr/2/0/11423

.NET Framework: 781. C# - OpenCvSharp 사용 시 포인터를 이용한 속도 향상
; https://www.sysnet.pe.kr/2/0/11567

개발 환경 구성: 447. Visual Studio Code에서 OpenCvSharp 개발 환경 구성
; https://www.sysnet.pe.kr/2/0/11971

Graphics: 38. C# - OpenCvSharp.VideoWriter에 BMP 파일을 1초씩 출력하는 예제
; https://www.sysnet.pe.kr/2/0/12485




C# - OpenCvSharp.VideoWriter에 BMP 파일을 1초씩 출력하는 예제

마침 질문도 있으니,

[WPF/OpenCV] 이미지->영상 저장에 대해서 질문 드립니다!!
; https://www.sysnet.pe.kr/3/0/5447

오랜만에 OpenCvSharp을 다뤄보겠습니다. ^^ 간략하게 개발 환경 구성하고,

Visual Studio Code에서 OpenCvSharp 개발 환경 구성
; https://www.sysnet.pe.kr/2/0/11971

Bitmap 파일로부터 Mat을 반환하는 간단한 도우미 타입을 만든 후,

using OpenCvSharp;
using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace WindowsFormsApp1
{
    public class MatBitmap : IDisposable
    {
        string _filePath;
        Image _img;
        Bitmap _bitmap;
        BitmapData _data;
        Mat _mat;

        public MatBitmap(string filePath)
        {
            _filePath = filePath;
        }

        public Mat Mat
        {
            get
            {
                if (_mat == null)
                {
                    _mat = LoadBitmap(_filePath);
                }

                return _mat;
            }
        }

        public Mat LoadBitmap(string filePath)
        {
            _img = Bitmap.FromFile(filePath);

            Rectangle imgSize = new Rectangle(0, 0, _img.Width, _img.Height);
            _bitmap = new Bitmap(_img);
            _data = _bitmap.LockBits(
                    imgSize, System.Drawing.Imaging.ImageLockMode.ReadOnly, _img.PixelFormat);

            MatType type = MatType.CV_8UC3;

            switch (img.PixelFormat)
            {
                case PixelFormat.Format32bppArgb:
                    type = MatType.CV_8UC4;
                    break;
            }

            return new Mat(img.Height, img.Width, type, data.Scan0);
        }

        public void Dispose()
        {
            if (_data != null)
            {
                if (_bitmap != null)
                {
                    _bitmap.UnlockBits(_data);
                    _bitmap.Dispose();
                    _bitmap = null;
                }

                _data = null;
            }

            if (_img != null)
            {
                _img.Dispose();
                _img = null;
            }
        }
    }
}

이렇게 사용하면,

using OpenCvSharp;
using System;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    // Install-Package OpenCvSharp4
    // Install-Package OpenCvSharp4.Windows
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MatBitmap[] bitmap = new MatBitmap[] {
            new MatBitmap("640x480_1.png"),
            new MatBitmap("640x480_2.png"),
            new MatBitmap("640x480_3.png") };

            int fps = 10;

            using (VideoWriter writer = new VideoWriter("test.avi", FourCC.XVID, fps, bitmap[0].Mat.Size(), true))
            {
                for (int i = 0; i < bitmap.Length; i++)
                {
                    for (int j = 0; j < fps; j++)
                    {
                        writer.Write(bitmap[i].Mat);
                    }

                    bitmap[i].Dispose();
                }
            }
        }
    }
}

3장의 "640x480_?.png" 파일을 읽어 각각 1초에 해당하는 분량으로 VideoWriter에 프레임을 쓰니 3초짜리 동영상이 만들어집니다. 굳이 더 이상 자세하게 설명할 것이 없군요. ^^

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




위의 예제에 기반을 둬 질문에 대한 답변을 하자면, 그러니까 결국 UDP 통신으로 전송하는 데이터는 _bitmap.LockBits로 얻은 IntPtr이 가리키는 버퍼이기만 하면 됩니다. 그것을 받아서 VideoWriter로 쓰면 되는데, 단지 UDP의 특성상 전송에 대한 신뢰성을 확보할 수 없으므로 (10 fps인 경우) 1초에 해당하는 10 frame 데이터를 온전히 받는 것을 기대해서는 안 됩니다.

따라서, 이미지 데이터와 함께 부가 헤더를 붙여 통신 프로토콜을 맞춰야 합니다. 가령, 일련번호도 함께 전송하고 수신 측에서는 일련번호가 순서대로 오지 않는 것을 감안해 몇 초 정도 버퍼링을 하다가 그래도 맞춰지지 않는 프레임은 그냥 이전 번호에 해당하는 프레임을 연이어 쓰는 식으로 보완을 해야 합니다.

게다가 위의 소스 코드에서는 단순히 raw 이미지 데이터를 다루고 있지만, 통신이 관여한다면 다양한 압축 방식을 고려하는 것이 좀 더 현실적일 수 있습니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 1/20/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 31  32  33  34  35  36  37  38  39  40  41  42  43  [44]  45  ...
NoWriterDateCnt.TitleFile(s)
12528정성태2/1/20219506개발 환경 구성: 534. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 윈도우 환경
12527정성태2/1/20219733개발 환경 구성: 533. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 리눅스 환경파일 다운로드1
12526정성태2/1/20217577개발 환경 구성: 532. Azure Devops의 파이프라인 빌드 시 snk 파일 다루는 방법 - Secure file
12525정성태2/1/20217282개발 환경 구성: 531. Azure Devops - 파이프라인 실행 시 빌드 이벤트를 생략하는 방법
12524정성태1/31/20218323개발 환경 구성: 530. 기존 github 프로젝트를 Azure Devops의 빌드 Pipeline에 연결하는 방법 [1]
12523정성태1/31/20218334개발 환경 구성: 529. 기존 github 프로젝트를 Azure Devops의 Board에 연결하는 방법
12522정성태1/31/20219836개발 환경 구성: 528. 오라클 클라우드의 리눅스 VM - 9000 MTU Jumbo Frame 테스트
12521정성태1/31/20219872개발 환경 구성: 527. 이더넷(Ethernet) 환경의 TCP 통신에서 MSS(Maximum Segment Size) 확인 [1]
12520정성태1/30/20218368개발 환경 구성: 526. 오라클 클라우드의 VM에 ping ICMP 여는 방법
12519정성태1/30/20217488개발 환경 구성: 525. 오라클 클라우드의 VM을 외부에서 접근하기 위해 포트 여는 방법
12518정성태1/30/202124934Linux: 37. Ubuntu에 Wireshark 설치 [2]
12517정성태1/30/202112520Linux: 36. 윈도우 클라이언트에서 X2Go를 이용한 원격 리눅스의 GUI 접속 - 우분투 20.04
12516정성태1/29/20219177Windows: 188. Windows - TCP default template 설정 방법
12515정성태1/28/202110387웹: 41. Microsoft Edge - localhost에 대해 http 접근 시 무조건 https로 바뀌는 문제 [3]
12514정성태1/28/202110695.NET Framework: 1021. C# - 일렉트론 닷넷(Electron.NET) 소개 [1]파일 다운로드1
12513정성태1/28/20218702오류 유형: 698. electronize - User Profile 디렉터리에 공백 문자가 있는 경우 빌드가 실패하는 문제 [1]
12512정성태1/28/20218512오류 유형: 697. The program can't start because VCRUNTIME140.dll is missing from your computer. Try reinstalling the program to fix this problem.
12511정성태1/27/20218255Windows: 187. Windows - 도스 시절의 8.3 경로를 알아내는 방법
12510정성태1/27/20218639.NET Framework: 1020. .NET Core Kestrel 호스팅 - Razor 지원 추가 [1]파일 다운로드1
12509정성태1/27/20219583개발 환경 구성: 524. Jupyter Notebook에서 C#(F#, PowerShell) 언어 사용을 위한 환경 구성 [3]
12508정성태1/27/20218184개발 환경 구성: 523. Jupyter Notebook - Slide 플레이 버튼이 없는 경우
12507정성태1/26/20218307VS.NET IDE: 157. Visual Studio - Syntax Visualizer 메뉴가 없는 경우
12506정성태1/25/202111574.NET Framework: 1019. Microsoft.Tye 기본 사용법 소개 [1]
12505정성태1/23/20219343.NET Framework: 1018. .NET Core Kestrel 호스팅 - Web API 추가 [1]파일 다운로드1
12504정성태1/23/202110464.NET Framework: 1017. .NET 5에서의 네트워크 라이브러리 개선 (2) - HTTP/2, HTTP/3 관련 [1]
12503정성태1/21/20218734오류 유형: 696. C# - HttpClient: Requesting HTTP version 2.0 with version policy RequestVersionExact while HTTP/2 is not enabled.
... 31  32  33  34  35  36  37  38  39  40  41  42  43  [44]  45  ...