项目 4 任务 2 网络摄像机:PictureBox、Image / Bitmap、照片列表
- 摄像头:自绘东围墙场景(Camera/scene.svg),按云台位置切成 640×480 帧(build-frames.ts); Pan 每次转一格,红外对射被遮挡时画面出现翻墙的人;类名、委托、事件参数与教材 dll 一致, ImageRead 每 250 ms 在后台线程触发 - Image / Bitmap 保存真实图片数据:Save、FromFile、FromStream,文件夹不存在时报 GDI+ 一般性错误; 图片每张只发给浏览器一次(按内容哈希缓存) - 程序所在目录(AppDomain.CurrentDomain.BaseDirectory,编译检查单独放行)和当前目录指向可写的 bin/Debug, 沙箱里在沙箱的临时目录 - PictureBox(SizeMode、BorderStyle);设计器工具箱加"图片框";运行区显示程序保存的图片,点开看大图; 实训台摄像头图标显示开启状态 - 评分规则加图片框显示图片、摄像头开关与转向、保存图片三种检查;示例 p4-t2-网络摄像机 - 测试:摄像头端到端、图片读写与程序目录、AppDomain 编译检查、评分出错情况 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4ed9450c02
commit
6b088240da
76 files changed
+1290
-14
No files matched your search
Generated
+166
@@ -0,0 +1,166 @@
|
||||
namespace 网络摄像机
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows 窗体设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.btn_up = new System.Windows.Forms.Button();
|
||||
this.btn_left = new System.Windows.Forms.Button();
|
||||
this.btn_right = new System.Windows.Forms.Button();
|
||||
this.btn_down = new System.Windows.Forms.Button();
|
||||
this.btn_camera = new System.Windows.Forms.Button();
|
||||
this.btn_open = new System.Windows.Forms.Button();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.txt_ip = new System.Windows.Forms.TextBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.BackColor = System.Drawing.Color.Black;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(25, 41);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(640, 480);
|
||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||
this.pictureBox1.TabIndex = 0;
|
||||
this.pictureBox1.TabStop = false;
|
||||
//
|
||||
// btn_up
|
||||
//
|
||||
this.btn_up.Location = new System.Drawing.Point(763, 166);
|
||||
this.btn_up.Name = "btn_up";
|
||||
this.btn_up.Size = new System.Drawing.Size(33, 33);
|
||||
this.btn_up.TabIndex = 1;
|
||||
this.btn_up.Text = "↑";
|
||||
this.btn_up.UseVisualStyleBackColor = true;
|
||||
this.btn_up.Click += new System.EventHandler(this.btn_up_Click);
|
||||
//
|
||||
// btn_left
|
||||
//
|
||||
this.btn_left.Location = new System.Drawing.Point(707, 219);
|
||||
this.btn_left.Name = "btn_left";
|
||||
this.btn_left.Size = new System.Drawing.Size(33, 33);
|
||||
this.btn_left.TabIndex = 2;
|
||||
this.btn_left.Text = "←";
|
||||
this.btn_left.UseVisualStyleBackColor = true;
|
||||
this.btn_left.Click += new System.EventHandler(this.btn_left_Click);
|
||||
//
|
||||
// btn_right
|
||||
//
|
||||
this.btn_right.Location = new System.Drawing.Point(820, 219);
|
||||
this.btn_right.Name = "btn_right";
|
||||
this.btn_right.Size = new System.Drawing.Size(33, 33);
|
||||
this.btn_right.TabIndex = 3;
|
||||
this.btn_right.Text = "→";
|
||||
this.btn_right.UseVisualStyleBackColor = true;
|
||||
this.btn_right.Click += new System.EventHandler(this.btn_right_Click);
|
||||
//
|
||||
// btn_down
|
||||
//
|
||||
this.btn_down.Location = new System.Drawing.Point(763, 268);
|
||||
this.btn_down.Name = "btn_down";
|
||||
this.btn_down.Size = new System.Drawing.Size(33, 33);
|
||||
this.btn_down.TabIndex = 4;
|
||||
this.btn_down.Text = "↓";
|
||||
this.btn_down.UseVisualStyleBackColor = true;
|
||||
this.btn_down.Click += new System.EventHandler(this.btn_down_Click);
|
||||
//
|
||||
// btn_camera
|
||||
//
|
||||
this.btn_camera.Location = new System.Drawing.Point(743, 347);
|
||||
this.btn_camera.Name = "btn_camera";
|
||||
this.btn_camera.Size = new System.Drawing.Size(75, 33);
|
||||
this.btn_camera.TabIndex = 7;
|
||||
this.btn_camera.Text = "拍照";
|
||||
this.btn_camera.UseVisualStyleBackColor = true;
|
||||
this.btn_camera.Click += new System.EventHandler(this.btn_camera_Click);
|
||||
//
|
||||
// btn_open
|
||||
//
|
||||
this.btn_open.Location = new System.Drawing.Point(763, 219);
|
||||
this.btn_open.Name = "btn_open";
|
||||
this.btn_open.Size = new System.Drawing.Size(33, 33);
|
||||
this.btn_open.TabIndex = 9;
|
||||
this.btn_open.Text = "开";
|
||||
this.btn_open.UseVisualStyleBackColor = true;
|
||||
this.btn_open.Click += new System.EventHandler(this.btn_open_Click);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(685, 69);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(53, 12);
|
||||
this.label1.TabIndex = 10;
|
||||
this.label1.Text = "摄像机IP";
|
||||
//
|
||||
// txt_ip
|
||||
//
|
||||
this.txt_ip.Location = new System.Drawing.Point(744, 66);
|
||||
this.txt_ip.Name = "txt_ip";
|
||||
this.txt_ip.Size = new System.Drawing.Size(111, 21);
|
||||
this.txt_ip.TabIndex = 11;
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(884, 562);
|
||||
this.Controls.Add(this.txt_ip);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.btn_open);
|
||||
this.Controls.Add(this.btn_camera);
|
||||
this.Controls.Add(this.btn_down);
|
||||
this.Controls.Add(this.btn_right);
|
||||
this.Controls.Add(this.btn_left);
|
||||
this.Controls.Add(this.btn_up);
|
||||
this.Controls.Add(this.pictureBox1);
|
||||
this.Name = "Form1";
|
||||
this.Text = "网络摄像机";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.Button btn_up;
|
||||
private System.Windows.Forms.Button btn_left;
|
||||
private System.Windows.Forms.Button btn_right;
|
||||
private System.Windows.Forms.Button btn_down;
|
||||
private System.Windows.Forms.Button btn_camera;
|
||||
private System.Windows.Forms.Button btn_open;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox txt_ip;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using DeviceCtrlLibrary;
|
||||
|
||||
namespace 网络摄像机
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
static string CameraPath = AppDomain.CurrentDomain.BaseDirectory + "Camera/";//拍照保存路径
|
||||
static string IpCameraIPAddress = "192.168.14.131";//网络摄像机IP
|
||||
bool IsOpen = false;
|
||||
Image ReadImage = null;//存储摄像机图片
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
//判断拍照保存文件夹是否存在,若不存在则先创建
|
||||
if (!Directory.Exists(CameraPath))
|
||||
Directory.CreateDirectory(CameraPath);
|
||||
DeviceCtrlHelper.ipCameraHelper.ImageRead += ipCameraHelper_ImageRead;//绑定图片显示事件
|
||||
}
|
||||
|
||||
void ipCameraHelper_ImageRead(ImageReadEvenArgs e)
|
||||
{
|
||||
ReadImage = e.img;//保存摄像机拍到的图片
|
||||
pictureBox1.Image = ReadImage;//显示在图片框上
|
||||
}
|
||||
|
||||
private void btn_open_Click(object sender, EventArgs e)
|
||||
{
|
||||
IsOpen = !IsOpen;
|
||||
if (IsOpen)
|
||||
{
|
||||
IpCameraIPAddress = txt_ip.Text;
|
||||
DeviceCtrlHelper.ipCameraHelper.Open(IpCameraIPAddress, "admin", "");//用户名admin,密码为空
|
||||
DeviceCtrlHelper.ipCameraHelper.Start();//开始传送图像
|
||||
btn_open.Text = "关";
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceCtrlHelper.ipCameraHelper.Stop();//停止传送图像
|
||||
btn_open.Text = "开";
|
||||
}
|
||||
}
|
||||
|
||||
private void btn_up_Click(object sender, EventArgs e)
|
||||
{
|
||||
DeviceCtrlHelper.ipCameraHelper.PanUp();//向上转
|
||||
}
|
||||
|
||||
private void btn_down_Click(object sender, EventArgs e)
|
||||
{
|
||||
DeviceCtrlHelper.ipCameraHelper.PanDown();//向下转
|
||||
}
|
||||
|
||||
private void btn_left_Click(object sender, EventArgs e)
|
||||
{
|
||||
DeviceCtrlHelper.ipCameraHelper.PanLeft();//向左转
|
||||
}
|
||||
|
||||
private void btn_right_Click(object sender, EventArgs e)
|
||||
{
|
||||
DeviceCtrlHelper.ipCameraHelper.PanRight();//向右转
|
||||
}
|
||||
|
||||
private void btn_camera_Click(object sender, EventArgs e)
|
||||
{
|
||||
//拍照:把当前图像以时间命名保存到Camera文件夹
|
||||
if (ReadImage != null)
|
||||
ReadImage.Save(CameraPath + DateTime.Now.ToString("yyyyMMdd_HH mm ss") + ".jpg");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace 网络摄像机
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# 评分规则:书上评价表的功能项。每项单独启动一次程序,按步骤操作,核对结果。
|
||||
# 格式说明见 server/src/grading/checks.ts
|
||||
- title: 能正确打开、关闭摄像机
|
||||
steps:
|
||||
- text: { control: txt_ip, value: 192.168.2.50 }
|
||||
- click: btn_open
|
||||
- expect: { control: btn_open, text: 关, desc: 按钮文字变成"关" }
|
||||
- expect: { camera: on }
|
||||
- click: btn_open
|
||||
- expect: { control: btn_open, text: 开, desc: 按钮文字变回"开" }
|
||||
- expect: { camera: off }
|
||||
|
||||
- title: 能正确显示图像
|
||||
steps:
|
||||
- text: { control: txt_ip, value: 192.168.2.50 }
|
||||
- click: btn_open
|
||||
- expect: { control: pictureBox1, image: true, within: 3s, desc: 显示摄像机拍到的图像 }
|
||||
|
||||
- title: 能控制摄像机上下左右旋转
|
||||
steps:
|
||||
- text: { control: txt_ip, value: 192.168.2.50 }
|
||||
- click: btn_open
|
||||
- click: btn_up
|
||||
- expect: { camera: up, desc: 点"↑"后向上转 }
|
||||
- click: btn_left
|
||||
- expect: { camera: left, desc: 点"←"后向左转 }
|
||||
- click: btn_down
|
||||
- click: btn_down
|
||||
- expect: { camera: down, desc: 点"↓"后向下转 }
|
||||
- click: btn_right
|
||||
- click: btn_right
|
||||
- expect: { camera: right, desc: 点"→"后向右转 }
|
||||
|
||||
- title: 能抓拍摄像机当前图像
|
||||
steps:
|
||||
- text: { control: txt_ip, value: 192.168.2.50 }
|
||||
- click: btn_open
|
||||
- expect: { control: pictureBox1, image: true, within: 3s, desc: 显示摄像机拍到的图像 }
|
||||
- click: btn_camera
|
||||
- expect: { savedImage: Camera/, desc: 把照片保存到 Camera 文件夹 }
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "项目4 任务2 控制网络摄像机",
|
||||
"source": "教材书 p78–81,界面取自配套参考工程,标签文字按书上表格改为“摄像机IP”;补上书上漏写的 using System.IO;"
|
||||
}
|
||||
Reference in new issue
Block a user