如何使用OpenCV为桌面和Web构建简单的Webcam应用程序(二)
Dynamic Web TWAIN是一个专为Web应用程序设计的TWAIN扫描识别控件。你只需在TWAIN接口写几行代码,就可以用兼容TWAIN的扫描仪扫描文档或从数码相机/采集卡中获取图像。然后用户可以编辑图像并将图像保存为多种格式,用户可保存图像到远程数据库或者SharePoint。这个TWAIN控件还支持上传和处理本地图像。
在大流行期间,由于社交距离遥远,对相机应用程序的需求激增。因此,我收集了一些用不同编程语言实现的基本OpenCV网络摄像头示例代码,并构建了一些用于远程网络摄像头访问的简单Web应用程序。希望这对开始构建网络摄像头应用程序的人有所帮助。在本文中,我将使用JavaScript,C#,Python和Golang。
从任何Web浏览器访问远程网络摄像头
要实现远程网络摄像头访问,我只需要创建一个带有图像元素的简单HTML页面并启动一个简单的HTTP服务器,即可通过HTTP GET请求连续发送网络摄像头帧。为了使代码尽可能简单,我只使用了四种编程语言的内置HTTP API和OpenCV视频捕获API。
Node.js
创建一个简单的HTML页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="//www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Webcam</title>
</head>
<body>
<img id="image"/>
<script type="text/javascript">
var image = document.getElementById('image');
function refresh() {
image.src = "/image?" + new Date().getTime();
image.onload= function(){
setTimeout(refresh, 30);
}
}
refresh();
</script>
</body>
</html>
在服务器端,使用HTTP模块创建一个简单的Web服务器:
const http = require('http'); var server = http.createServer(function (req, res) { if (req.url === '/' || req.url === '/index.htm') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.write(html); res.end(); } else if (req.url.startsWith("/image")) { res.writeHead(200, { 'Content-Type': 'image/jpeg' }); res.write(img); res.end(); } else res.end('Invalid Request!'); }); server.listen(2020);分析请求URL,然后发送相应的响应。同时,创建一个计时器以捕获网络摄像头帧并将其编码为JPEG格式:
var img = null; function capture() { var frame = wCap.read() if (frame.empty) { wCap.reset(); frame = wCap.read(); } img = cv.imencode('.jpg', frame); setTimeout(capture, 30); } capture();要通过双击打开HTML文件,请将相对图像路径更改为绝对图像路径:
image.src = "//localhost:2020/image?" + new Date().getTime();C#
受本杰明·萨默顿(Benjamin Summerton)的要旨启发,我创建了HTTP服务器,如下所示:
using System; using System.IO; using System.Text; using System.Net; using System.Threading.Tasks; using OpenCvSharp; namespace Web { class Program { public static HttpListener listener; public static string url = "//localhost:2020/"; public static string pageData = "" + "" + "" + "Python如何使用OpenCV为桌面和Web构建简单的Webcam应用程序(二)-Dynamic Web TWAIN使用教程-慧都网 " + "" + "" + ""+ " "+ "" + ""; public static VideoCapture capture = new VideoCapture(0); public static async Task HandleIncomingConnections() { while (true) { HttpListenerContext ctx = await listener.GetContextAsync(); HttpListenerRequest req = ctx.Request; HttpListenerResponse resp = ctx.Response; if ((req.HttpMethod == "GET") && (req.Url.AbsolutePath.StartsWith("/image"))) { resp.ContentType = "image/jpeg"; using (Mat image = new Mat()) { capture.Read(image); Cv2.ImEncode(".jpg", image, out var imageData); await resp.OutputStream.WriteAsync(imageData, 0, imageData.Length); resp.Close(); } } else { // Write the response info byte[] data = Encoding.UTF8.GetBytes(pageData); resp.ContentType = "text/html"; resp.ContentEncoding = Encoding.UTF8; resp.ContentLength64 = data.LongLength; // Write out to the response stream (asynchronously), then close it await resp.OutputStream.WriteAsync(data, 0, data.Length); resp.Close(); } } } static void Main(string[] args) { // Create a Http server and start listening for incoming connections listener = new HttpListener(); listener.Prefixes.Add(url); listener.Start(); Console.WriteLine("Listening for connections on {0}", url); // Handle requests Task listenTask = HandleIncomingConnections(); listenTask.GetAwaiter().GetResult(); // Close the listener listener.Close(); } } }
使用Python的内置HTTP服务器类非常方便。我们需要做的是定义一个用于处理HTTP请求的自定义处理程序:
import http.server import socketserver class MyHandler(http.server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/': self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(bytes(pageData, "utf8")) elif self.path.startswith('/image'): self.send_response(200) self.send_header("Content-type", "image/jpeg") self.end_headers() ret, frame = cap.read() _, jpg = cv2.imencode(".jpg", frame) self.wfile.write(jpg) else: self.send_response(404) with socketserver.TCPServer(("", PORT), MyHandler) as httpd: print("Serving at port ", PORT) try: httpd.serve_forever() except: passGoang
像Python一样,很容易在30秒内设置HTTP Web服务器:
func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { pageData := "" + "" + "" + "完成所有操作后,我可以运行Web服务器并访问localhost:2020以从任何桌面Web浏览器查看网络摄像头视频流。如何使用OpenCV为桌面和Web构建简单的Webcam应用程序(二)-Dynamic Web TWAIN使用教程-慧都网 " + "" + "" + "" + " " + "" + "" w.Header().Set("Content-Type", "text/html") w.Write([]byte(pageData)) } else if strings.HasPrefix(r.URL.Path, "/image") { webcam.Read(&img) jpg, _ := gocv.IMEncode(".jpg", img) w.Write(jpg) } else { fmt.Fprintf(w, "Page Not Found") } } func main() { fmt.Println("Running at port 2020...") webcam, _ = gocv.OpenVideoCapture(0) img = gocv.NewMat() http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":2020", nil)) webcam.Close() }
也可以从我的移动网络浏览器访问该页面。