本程式使用 Logitech C922 Pro WebCam, 接入樹莓派usb, 並由樹莓派透過Wifi傳出所取得的影像到Server(Win10).
樹莓派作業系統為 Raspbian Server版本, 程式使用Python3 進行傳送
Server為Win10, 使用C# Socket 接收傳進來的影像
C#執行結果如下
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) { Listbuf = 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()