Python 셀레니움 이미지 크롤링

프로그래밍 언어 2020. 11. 2. 15:35

www.youtube.com/watch?v=1b7pXC1-IbE

 

와우~

설정

트랙백

댓글

HTTP 3핸드 쉐이킹 캡쳐

통신/TCP_IP 2020. 10. 12. 10:00

스트림 데이터를 받는데,

3핸드쉐이킹 후에 데이터를 주고 받는 것을 캡쳐해 봤다.

HTTP REST API의 GET으로 보낼 때, HEX 값 같은 것이 아닌 문자열을 주고 받는 것을 확인하였다.

위에

'빨강 {' 이 3핸드 쉐이킹이고

'빨강 -' 가 REST API의 GET, 밑에 빨강 박스가 그 내용이다.

 

 

 

 

 

 

 

'통신 > TCP_IP' 카테고리의 다른 글

Ethernet, IP, TCP, UDP Frame  (0) 2014.10.15
TCP/IP 4 계층  (0) 2014.10.15

설정

트랙백

댓글

C# RGB 출력, YUV420 -> RGB로 출력

프로그래밍 언어/C# 2020. 9. 1. 16:17

Raspberry Pi Zero W에 카메라 이미지를 PC에 전송하여 출력하는 것을 작업하고 있다.

 

그런데.... Raspberry Pi 에서 큰 문제가 생겼다...

 

자료를 찾아보니 대부분 OpenCV를 사용하여 데이터를 보내길래

 

OpenCV를 깔아봤는데.... 'Illegal instruction'이라고 에러가 떠서 동작이 안된다.

 

아무리 삽질을 해봐도 해결 방법을 못 찾았다ㅠㅠ;;

 

 

그래서 다른 방법을 찾던 중, 라즈베리 기본 설치 프로그램 중에

 

raspistill, raspivid, raspiyuv, raspividyuv를 사용해서 데이터를 보낼 방법을 찾았다.

 

 

 

라즈베리에서 카메라 실행은

raspividyuv -w 480 -h 320 -fps 5 -t 0 -l -o tcp://192.168.0.125:7777

이 명령 사용

 

YUV420 포멧으로 raw 데이터 보냄.

 

그래서 C#에서 화면에 그려줄때

480x320 사이즈로

한 프레임당 230400 bytes 이다.

 

0~153600 까지는 Y 값

153600~192000 까지는 U 값

192000~230400 까지 V 값

으로 구성되어 있다.

 

소스 ProcDrawingBuf() 함수에 38400 은 V값과 U 값 크기이다.

 

곳곳에 마이크 녹음이랑 사운드 출력도 있다....

 

 

--- MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Resources; // test.jpg
using System.IO.Ports; // SerialPort
using System.Windows.Threading; // DispatcherPriority
using System.Threading; // Thread
using NAudio.Wave;
using System.Drawing; // Bitmap
using System.IO;
using System.Net.Sockets; // TcpClient
using System.Net;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace YUVRGB_Ctrl
{
    ///
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// 
    public partial class MainWindow : System.Windows.Window
    {
        private SerialPort sp;  // COM 포트
        private bool portOpen;  // 포트 열림 여부

        private WaveIn sourceStream = null; // 녹음 핸들?

        private Thread t1; // 네트워크 스트림 thread
        private Thread t2; // 비트맵 thread
        private string destIP; // 원격지 IP
        private bool ipOpen; // 원격지 열기 닫기 여부

        private TcpClient tc; // 원격지 주소
        private NetworkStream stream; // 원격지 스트림

        private byte[] streamBuf = new byte[230400];
        private byte[] drawingBuf = new byte[230400];

        public MainWindow()
        {
            InitializeComponent();

            sp = null;
            portOpen = false;
            t1 = null;
            ipOpen = false;

            // 임시 이미지 그리기
            //BitmapImage drawImg = new BitmapImage(new Uri(@"C:\Users\root\Documents\Visual Studio 2017\Projects\KLabs RGControl\KLabs RGControl\test.jpg"));
            BitmapImage drawImg = new BitmapImage(new Uri("test.jpg", UriKind.Relative));
            imgTest.Source = drawImg;
            imgTest.Visibility = Visibility.Hidden;

            // 키보드 처리 인터럽트 추가
            this.KeyDown += new KeyEventHandler(FuncKeyDown);
        }

        // 키보드 처리
        private void FuncKeyDown(object sender, KeyEventArgs e)
        {
            switch(e.Key)
            {
                case Key.Escape:
                    this.Close();
                    break;
            }
        }

        // 메인 윈도우창 이동
        private void Window_MouseLeftBtnDown(object sender, RoutedEventArgs e)
        {
            Cursor = Cursors.SizeAll;
            this.DragMove();
        }

        private void Window_MouseLeftBtnUp(object sender, RoutedEventArgs e)
        {
            Cursor = Cursors.Arrow;
        }

        // exit 버튼
        private void BtnExit_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        // connect 버튼
        private void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            // 연결되어 있으면 기존 연결 끊기
            if (ipOpen == true)
            {
                // 스트림과 TcpClient 객체 닫기
                stream.Close();
                tc.Close();
                ipOpen = false;
            }

            Window1 infoWindown = new Window1();
            infoWindown.OnChildDataEvent += new Window1.OnChildDataHandler(GetDataFromChild);
            infoWindown.ShowDialog();
        }

        // 카메라, 센서 연결.
        private void GetDataFromChild(string destIP, string comPort)
        {
            // COM 포트 열기
            //OpenComport(comPort);

            // IP 카메라 연결
            OpenCam(destIP);
        }

        // COM 포트 열기
        private void OpenComport(string destCom)
        {
            Console.WriteLine(destCom);
            // COM 연결 상태 확인
            if(sp == null)
            {
                try
                {
                    // 1. SerialPort 클래스 객체 생성
                    sp = new SerialPort();

                    // 2. SerialPort 포트 셋팅 설정
                    sp.PortName = destCom;
                    sp.BaudRate = (int)115200;
                    sp.DataBits = 8;
                    sp.Parity = Parity.None;
                    sp.StopBits = StopBits.One;
                    sp.Handshake = Handshake.None;
                    sp.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);

                    // 3. 시리얼포트 오픈
                    sp.Open();
                    portOpen = true;
                }
                catch
                {
                    MessageBox.Show("COM 포트 열기 에러");
                }
            }
        }

        // COM 포트에서 읽은 데이터 처리
        public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if ((portOpen == true) && (sp.BytesToRead >= 0))
            {
                try
                {
                    var stBulider = new StringBuilder();
                    stBulider.Append(sp.ReadLine());
                    //buf = sp.ReadLine();
                    if (stBulider[0] == '0')
                    {
                        stBulider.Append(sp.ReadLine());
                        stBulider.Append(sp.ReadLine());
                        stBulider.Append(sp.ReadLine());
                        stBulider.Append(sp.ReadLine());
                        /*
                        buf += sp.ReadLine();
                        buf += sp.ReadLine();
                        buf += sp.ReadLine();
                        buf += sp.ReadLine();
                        */
                        //buf = buf.Replace("\r", " ");

                        Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
                        {
                            labelSensorStatus.Content = stBulider.ToString();
                        }));
                        //this.labelSerial.Content = buf;
                    }
                }
                catch
                { }
            }
        }

        // IP 카메라 연결
        private void OpenCam(string destIP2)
        {
            destIP = destIP2;
            Console.WriteLine(destIP2);
            imgTest.Visibility = Visibility.Visible;
            labelNetworkStatus.Visibility = Visibility.Hidden;

            // 카메라 데이터 스레드 처리
            /*
            if(t1 == null)
            {
                t1.Abort();
            }
            */
            int aTmp;

            t1 = new Thread(new ThreadStart(ProcCamData));
            t1.Start();
        }

        // IP 카메라 데이터 처리
        private void ProcCamData()
        {
            byte[] outbuf = new byte[15000];
            int nbytes;
            int total;
            int i, f;
            string output;
            string sTime = System.DateTime.Now.ToString("mm:ss.ffffff");
            TcpClient tc = new TcpClient("192.168.0.125", 7777);
            NetworkStream stream = tc.GetStream();

            total = 0;
            i = 0;
            f = 0;
            while(true)
            {
                nbytes = stream.Read(outbuf, 0, outbuf.Length);
                // 한 프레임(230400) 처리
                if (total + nbytes >= 230400)
                {
                    Array.Copy(outbuf, 0, streamBuf, total, 230400 - total);
                    Array.Copy(streamBuf, drawingBuf, 230400);
                    Array.Copy(outbuf, 230400 - total, streamBuf, 0, nbytes - (230400 - total));
                    if(t2 == null)
                    {
                        t2 = new Thread(new ThreadStart(ProcDrawingBuf));
                        t2.Start();
                    }
                    else if ((t2.ThreadState & ThreadState.Stopped) == ThreadState.Stopped)
                    {
                        t2 = new Thread(new ThreadStart(ProcDrawingBuf));
                        t2.Start();
                    }
                    total = nbytes - (230400 - total);
                    f++;
                }
                else
                {
                    Array.Copy(outbuf, 0, streamBuf, total, nbytes);
                    total += nbytes;
                }
                i++;
                //output = Encoding.ASCII.GetString(outbuf, 0, nbytes);
                //Console.WriteLine($"{i} : {nbytes} ");// bytes: {output}");

                if (nbytes == 0)
                {
                    break;
                }
            }
            Console.WriteLine($"total : {i} {f}");
            Console.WriteLine($"Start time : {sTime}");
            Console.WriteLine($"End time : {System.DateTime.Now.ToString("mm:ss.ffffff")}");

            stream.Close();
            tc.Close();
        }

        private void ProcDrawingBuf()
        {
            Bitmap bitmap = new Bitmap(480, 320);
            BitmapData bmpData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, 480, 320), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            int k, uv;
            int bY, bU, bV;

            k = 0;
            uv = 0;
            unsafe
            {
                byte* ptr = (byte*)bmpData.Scan0.ToPointer();
                for (int i = 0; i < 320; i++)
                {
                    for (int j = 0; j < 480; j++)
                    {
                        if (uv >= 38400)
                        {
                            break;
                        }
                        bU = drawingBuf[320 * 480 + uv] - 128;
                        bV = drawingBuf[320 * 480 + 38400 + uv] - 128;
                        bY = drawingBuf[k];

                        // R
                        if (bV < 0)
                            ptr[bmpData.Stride * i + 3 * j + 2] = (byte)bY;
                        else
                            ptr[bmpData.Stride * i + 3 * j + 2] = (byte)(bY + (2.0790 * bV));

                        // G
                        if (bU < 0)
                            ptr[bmpData.Stride * i + 3 * j + 0] = (byte)bY;
                        else
                            ptr[bmpData.Stride * i + 3 * j + 0] = (byte)(bY + (1.4075 * bU));

                        // B
                        ptr[bmpData.Stride * i + 3 * j + 1] = (byte)(bY - (0.237633 * bV) - (0.337633 * bU));

                        k++;
                        if (j % 2 == 0)
                        {
                            uv++;
                        }
                    }
                    if (i % 2 == 0)
                    {
                        uv -= 240;
                    }
                }
                bitmap.UnlockBits(bmpData);
            }

            Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
            {
                imgTest.Source = BitmapToImageSource(bitmap);
            }));
            bitmap.Dispose();
        }

        public Bitmap ScreenCapture()
        {
            // 주화면의 크기 정보 읽기
            int width = (int)SystemParameters.PrimaryScreenWidth;
            int height = (int)SystemParameters.PrimaryScreenHeight;
            Bitmap scrbmp = new Bitmap(width, height);

            using (Graphics g = Graphics.FromImage(scrbmp))
            {
                g.CopyFromScreen(0, 0, 0, 0, scrbmp.Size, CopyPixelOperation.SourceCopy);
            }

            // Image에 캡처한 이미지를 뿌려주기 위해 Bitmap을 BitmapImage로 변환한다.
            using (MemoryStream memory = new MemoryStream())
            {
                scrbmp.Save(memory, ImageFormat.Bmp);
                memory.Position = 0;
                BitmapImage bitmapimage = new BitmapImage();
                bitmapimage.BeginInit();
                bitmapimage.StreamSource = memory;
                bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapimage.EndInit();
                imgTest.Source = bitmapimage;
            }

            return scrbmp;
        }

        BitmapImage BitmapToImageSource(Bitmap bitmap)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
                memory.Position = 0;
                BitmapImage bitmapimage = new BitmapImage();
                bitmapimage.BeginInit();
                bitmapimage.StreamSource = memory;
                bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapimage.EndInit();

                return bitmapimage;
            }
        }

        // 마이크 녹음 초기화
        public void RecodeMic()
        {
            sourceStream = new NAudio.Wave.WaveIn();
            sourceStream.BufferMilliseconds = 50;
            sourceStream.DeviceNumber = 0;
            sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(4800, NAudio.Wave.WaveIn.GetCapabilities(0).Channels);
            sourceStream.DataAvailable += new EventHandler(sourceStream_DataAvailable);
            sourceStream.StartRecording();
        }

        // 마이크 녹음 데이터 처리
        private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
        {
            byte[] encoded = e.Buffer;
            int i;
            float multiplier = 12.0f;   // Gain

            for (i = 0; i < encoded.Length; i = i + 2)
            {
                Int16 sample = BitConverter.ToInt16(encoded, i);
                sample = (Int16)(sample * multiplier);
                byte[] sampleBytes = BitConverter.GetBytes(sample);
                encoded[i] = sampleBytes[0];
                encoded[i + 1] = sampleBytes[1];
            }

            //encoded.CopyTo(recordingStream2, encoded.Length);
        }
    }
}

 

 

--- 실행화면

   - Raspberry pi zero w

 

   - PC

 

'프로그래밍 언어 > C#' 카테고리의 다른 글

C# 이미지 그리기, 출력  (0) 2020.08.21
C# NAudio MicroPhone 볼륨 조절  (0) 2020.08.20

설정

트랙백

댓글