WebCam

      在〈WebCam〉中尚無留言

本程式使用 Logitech C922 Pro WebCam, 接入樹莓派usb, 並由樹莓派透過Wifi傳出所取得的影像到Server(Win10).

c922pro

樹莓派作業系統為 Raspbian Server版本, 程式使用Python3 進行傳送

Server為Win10, 使用C# Socket 接收傳進來的影像

C#執行結果如下

webcam

C#主程式

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace WebCam
{
    public partial class MainWindow : Window
    {
        Socket SocketWatch = null;
        bool runFlag = true;
        public MainWindow()
        {
            InitializeComponent();
            int port = 8002;
            //IPAddress ip = IPAddress.Parse("192.168.1.2");
            IPAddress ip = IPAddress.Any;
            IPEndPoint ipe = new IPEndPoint(ip, port);
            SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SocketWatch.Bind(ipe);
            //將套接字的監聽佇列長度限制為20  
            SocketWatch.Listen(20);
            Thread watchThread = new Thread(WatchThread);
            //將窗體執行緒設定為與後臺同步,隨著主執行緒結束而結束  
            watchThread.IsBackground = true;
            watchThread.Start();
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                lblStatus.Content = "監聽中....";
            }));
        }
        void WatchThread()
        {
            Socket connection = null;
            while (runFlag)
            {
                try
                {
                    connection = SocketWatch.Accept();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                    rowStatus.Height = new GridLength(0);
                }));
                Thread receiveThread = new Thread(ReceiveThread);
                receiveThread.IsBackground = true;
                receiveThread.Start(connection);
            }
        }

        private void ReceiveThread(object socketclientpara)
        {
            Socket socket = socketclientpara as Socket;
            while (runFlag)
            {
                try
                {
                    byte[] buff = ReceiveAll(socket, 16);
                    byte[] byteCvImg = ReceiveAll(socket, Int64.Parse(Encoding.UTF8.GetString(buff, 0, 16)));
                    Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                        OpenCvSharp.Mat mat = OpenCvSharp.Cv2.ImDecode(byteCvImg, OpenCvSharp.ImreadModes.Color);
                        Bitmap bitmap=OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
                        BitmapImage image = GetImage(bitmap);
                        img.Source = image;
                    }));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Receive socket error : {0}", e.Message);
                }
            }
        }
        private byte[] ReceiveAll(Socket socket, long count)
        {
            List buf = new List();
            byte[] tmp = null;
            while (count > 0)
            {
                tmp = new byte[count]; //注意, buffer不能超出剩餘的大小, 否則會取到下一筆資料
                int c = socket.Receive(tmp);
                for (int i = 0; i < c; i++) { 
                    buf.Add(tmp[i]); 
                } 
                if (count > 0) count -= c;
            }
            return buf.ToArray();
        }
        //Bitmap to BitmapImage
        private BitmapImage GetImage(Bitmap bitmap)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                stream.Position = 0;
                BitmapImage image = new BitmapImage();
                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = stream;
                image.EndInit();
                image.Freeze();
                return image;
            }
        }

        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            runFlag = false;
            this.Close();
        }
    }
}

XAML

<Window x:Class="WebCam.MainWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:local="clr-namespace:WebCam"
 mc:Ignorable="d"
 Title="Mahal WebCam" Height="450" Width="800">
 <Grid>
 <Grid.RowDefinitions>
 <RowDefinition Height="*"/>
 <RowDefinition Height="30"/>
 <RowDefinition Height="30" x:Name="rowStatus"/>
 </Grid.RowDefinitions>
 <Image x:Name="img" Grid.Row="0"/>
 <Grid Grid.Row="1" Background="#FF32B2F8">
 <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
 <Button x:Name="btnExit" Content="離開" Width="100" Click="btnExit_Click"/>
 </StackPanel>
 </Grid>
 <Label x:Name="lblStatus" HorizontalContentAlignment="Center" Grid.Row="2" Background="#FFE5E5E5"/>
 </Grid>
</Window>

Python Client程式

#!/usr/bin/python3
import socket
import cv2
import numpy
import datetime
import time

TCP_IP = "mahaljsp.asuscomm.com"
TCP_PORT = 8002
sock = socket.socket()

cam = cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
runFlag=True
#sock.connect((TCP_IP, TCP_PORT))
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90]

while runFlag:
    ret, frame = cam.read()
    datetime_dt = datetime.datetime.today()  # 獲得當地時間
    datetime_str = datetime_dt.strftime("%Y/%m/%d %H:%M:%S")  # 格式化日期
    cv2.putText(frame,datetime_str,(10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255),2,cv2.LINE_AA)
    result, imgencode = cv2.imencode('.jpg', frame, encode_param)
    data = numpy.array(imgencode)
    byteData = data.tobytes()
    try:
        s='1234';
        sock.send( str(len(byteData)).ljust(16).encode(encoding='utf_8', errors='strict'))
        sock.send(byteData);
    except Exception as e:
        print("send error : ", e)
        sock = socket.socket()
        sock.connect((TCP_IP, TCP_PORT))

sock.close()
cv2.destroyAllWindows()

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *