本程式使用 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)
{
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()
