Skip to content

Commit 456b92e

Browse files
committed
chore: upload codes from other repo
1 parent d90bb26 commit 456b92e

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

exercise/28.02.2024/client.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import time
2+
3+
import cv2
4+
import socket
5+
import numpy as np
6+
import struct
7+
8+
9+
class Camera(object):
10+
# 摄像头类,采集视频,发送到服务器
11+
12+
# 创建类时打开摄像头
13+
def __init__(self, dest_ip, dest_port):
14+
# 打开摄像头
15+
self.myVC = cv2.VideoCapture(0)
16+
17+
# 创建套接字(用于主机与服务器端通讯)
18+
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
19+
20+
# 连接服务器
21+
self.client_socket.connect((dest_ip, dest_port))
22+
23+
# 定义了压缩后图片的绝对大小,160x120
24+
self.resolution = (1024, 720)
25+
26+
def run(self):
27+
try:
28+
# 循环发送图片
29+
while True:
30+
# 采集摄像头
31+
# 参数check为是否捕获成功,参数img为捕获影像
32+
# myVC.read()返回两个值
33+
check, img = self.myVC.read()
34+
35+
# 压缩图片
36+
37+
# 重置图片大小(防止摄像头拍出来的图片默认大小不同)
38+
img = cv2.resize(img, self.resolution)
39+
# 将img图片压缩为jpg格式(_, 指的是他第一个返回值用不上,丢弃了)
40+
_, img_encode = cv2.imencode('.jpg', img)
41+
# 转换为numpy格式数据
42+
img_code = np.array(img_encode)
43+
# 生成对应的二进制数据
44+
img_date = img_code.tobytes()
45+
46+
# 打印传输图片的数据大小
47+
print("Transmitting image data size:", len(img_date))
48+
49+
# 发送到服务器
50+
# i 表示4个字节,h 表示2个字节
51+
# ihh表示 1 2 3 个参数分别为 4 2 2 字节
52+
# 参数1传图片大小,参数2传图片宽度,参数3传图片高度,参数4传图片本身
53+
# struct是python提供的传定长数据(在此处为了让服务端分开哪到哪的数据为一张图片
54+
# 这里为什么要try呢?因为发送的图片过大会导致发送失败
55+
try:
56+
self.client_socket.send(
57+
struct.pack("ihh", len(img_date), self.resolution[0], self.resolution[1]) + img_date)
58+
except Exception as e:
59+
print("Error sending data:", e)
60+
continue # 继续当前循环
61+
# time.sleep(0.1)
62+
except KeyboardInterrupt:
63+
# 按下按键退出程序
64+
pass
65+
66+
def __del__(self):
67+
# 释放摄像头资源
68+
self.myVC.release()
69+
70+
# 关闭套接字
71+
self.client_socket.close()
72+
73+
74+
# 定义主函数
75+
def main():
76+
# 1. 获取链接的tcp服务器的IP
77+
dest_ip = input("请输入服务器IP:")
78+
dest_ip = dest_ip if dest_ip else "127.0.0.1"
79+
80+
# 2. 获取tcp服务器的端口
81+
dest_port = input("请输入服务器的端口:")
82+
dest_port = int(dest_port) if dest_port else 54609
83+
84+
# 3. 创建Camera对象
85+
camera = Camera(dest_ip, dest_port)
86+
87+
# 4. 调用对象run方法,为服务器传送摄像头数据
88+
camera.run()
89+
90+
pass
91+
92+
93+
if __name__ == '__main__':
94+
main()

exercise/28.02.2024/server.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from flask import Flask, render_template, Response
2+
import socket
3+
import cv2
4+
import numpy as np
5+
import struct
6+
7+
app = Flask(__name__)
8+
9+
# 创建一个UDP套接字
10+
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
11+
server_socket.bind(('127.0.0.1', 0)) # 绑定本地所有IP地址的随机端口
12+
13+
# 获取绑定后的端口号
14+
port = server_socket.getsockname()[1]
15+
print(f"Server is running on port {port}")
16+
17+
@app.route('/')
18+
def index():
19+
"""主页"""
20+
return render_template('index.html')
21+
22+
23+
def gen():
24+
"""生成器函数,用于获取视频流"""
25+
while True:
26+
# 接收数据包
27+
data, addr = server_socket.recvfrom(65507)
28+
29+
# 解包数据
30+
size, width, height = struct.unpack('ihh', data[:8])
31+
32+
# 重构图像
33+
img_decode = np.fromstring(data[8:], dtype=np.uint8)
34+
img = cv2.imdecode(img_decode, cv2.IMREAD_COLOR | cv2.IMREAD_ANYDEPTH)
35+
36+
# 编码图像
37+
ret, jpeg = cv2.imencode('.jpg', img)
38+
39+
# 构建帧数据
40+
frame = jpeg.tobytes()
41+
42+
# 生成multipart/x-mixed-replace格式的数据
43+
yield (b'--frame\r\n'
44+
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
45+
46+
47+
@app.route('/video_feed')
48+
def video_feed():
49+
"""视频流路由"""
50+
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
51+
52+
53+
if __name__ == '__main__':
54+
app.run(debug=True)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Video Stream</title>
7+
</head>
8+
<body>
9+
<h1>Video Stream</h1>
10+
<img src="{{ url_for('video_feed') }}" width="800" height="600" />
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)