Python 实现海康机器人工业相机 MV-CS050-10GC 的实时显示视频流及拍照功能(实时显示视频流同时可以进行拍照)
参考文档: https://www.cnblogs.com/miracle-luna/p/16960556.html#5138211
大佬的文档很详细但是不能在实时预览的情况下进行拍照(可能没有这个需求所以没做)废话不多说 上代码
1、添加依赖文件
将 C:\Program Files (x86)\MVS\Development\Samples\Python\ 目录下的 MvImport目录,copy到自己的工程目录下。
2、安装插件 DirectShow
1)进入第三方插件 DirectShow 路径
cd C:\Program Files (x86)\MVS\Development\ThirdPartyPlatformAdapter\DirectShow\x64\MvDSS2
2)安装 DirectShow
使用 管理员权限 运行 InstallDSSvc_x64.bat
(本人使用的是64位Windows操作系统,运行代码也是基于64位运行,故而使用该版本;32位系统在上一目录中也存在,大家可以根据实际情况进行安装)
3、安装依赖模块
1)安装 opencv-python
pip install opencv-python==4.1.2.30 -i https://pypi.tuna.tsinghua.edu.cn/simple
个人使用的是 Python 3.8.5,opencv-python 对应使用 4.1.2.30 版本即可。
如果使用的 opencv-python 的版本过高,可能报如下错误:
cv2.error: Unknown C++ exception from OpenCV code.
2)安装 Flask
pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
也可以指定 Flask 的版本,如:
pip install flask=2.2.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
4、核心代码
工程代码结构如下:
0)index.html
在工程中创建 templates 目录,用于存放 index.hml
<head>
</head>
<body>
<h1>拍照预览</h1>
<img src="{{ url_for('startPreview') }}" width="50%">
</body>
</html>
1)JsonResponse.py
用于规范返回给前端的数据类型,代码如下:
# -- coding: utf-8 --
class JsonResponse(object):
"""
统一的json返回格式
"""
def __init__(self, code, msg, data):
self.code = code
self.msg = msg
self.data = data
@classmethod
def success(cls, code=0, msg='success', data=None):
return cls(code, msg, data)
@classmethod
def error(cls, code=-1, msg='error', data=None):
return cls(code, msg, data)
def to_dict(self):
return {
"code": self.code,
"msg": self.msg,
"data": self.data
}
2)JsonFlask.py
用于重定义数据返回格式,代码如下:
# -- coding: utf-8 --
from flask import Flask, jsonify
from JsonResponse import *
class JsonFlask(Flask):
def make_response(self, rv):
"""视图函数可以直接返回: list、dict、None"""
if rv is None or isinstance(rv, (list, dict)):
rv = JsonResponse.success(rv)
if isinstance(rv, JsonResponse):
rv = jsonify(rv.to_dict())
return super().make_response(rv)
有人说怎么跟人家的一样啊!!!!这不是抄袭吗??
注意了不一样的地方来了!!!!
3)HikRobotCamera.py
核心代码文件,实现如下功能:
开始预览视频流、停止预览视频流、取一帧数据保存到本地、记录日志等功能。
代码如下:
# -- coding: utf-8 --
import cv2
from flask import Flask, render_template, Response
import sys
import msvcrt
import base64
import datetime
import logging
sys.path.append("./MvImport")
from MvCameraControl_class import *
from JsonResponse import *
from JsonFlask import *
logging.basicConfig(level=logging.DEBUG,#控制台打印的日志级别
filename='hikrobot.log',
filemode='a',##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
#a是追加模式,默认如果不写的话,就是追加模式
format=
'%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
#日志格式
)
# 这里配置一下 template_folder为当前目录,不然可以找不到 index.html
app = JsonFlask(__name__, template_folder='.')
# index
@app.route('/')
def index():
return render_template('./templates/index.html')
# 获取码流
def generate(cap):
# 捕获异常信息
try:
while True:
# 如果是关闭相机,先退出取视频流的循环
global open
if (not open):
break;
retgrab = cap.grab()
if retgrab == True:
logging.debug("Grab true")
ret1, frame = cap.retrieve()
# print(type(frame))
if frame is None:
logging.error("frame is None")
continue
ret1, jpeg = cv2.imencode('.jpg', frame)
jpg_frame = jpeg.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + jpg_frame + b'\r\n')
except Exception as e:
logging.error("generate error: %s" % str(e))
# 开始预览
@app.route('/startPreview')
def startPreview():
logging.info("======================================")
logging.info("start to preview video stream, current_time: " + str(datetime.datetime.now()))
# 全局变量,用于控制获取视频流的开关状态
global open
open = True
# 全局变量,获取视频连接
global cap
cap = cv2.VideoCapture(0)
if False == cap.isOpened():
logging.error("can't open camera")
quit()
else:
logging.info("start to open camera")
logging.info("open camera ok")
# 分辨率设置 2448*2048(海康机器人工业相机 MV-CS050-10GC)
# 分辨率的设置需要根据自己相机的分辨率来调节 设置的跟自己相机不一致的分辨率可能 可能会导致实时预览的时候显示不出来
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2448)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 2048)
# 帧率配置 可根据自己相机支持的最大帧率进行更改
cap.set(cv2.CAP_PROP_FPS, 15)
# _, frame = cap.read()
# cv2.imwrite("your_image_file_path.jpg", frame)
return Response(generate(cap), mimetype='multipart/x-mixed-replace;boundary=frame')
# 停止预览
@app.route('/stopPreview')
def stopPreview():
logging.info("======================================")
logging.info("stop to preview video stream, current_time: " + str(datetime.datetime.now()))
logging.info("start to close camera")
# 全局变量,用于停止循环
global open
open = False
logging.info("release resources start")
# 全局变量,用于释放相机资源
try:
global cap
cap.release()
cv2.destroyAllWindows()
except Exception as e:
logging.error("stopPreview error: %s" % str(e))
logging.info("release resources end")
logging.info("camera closed successfully, current_time: " + str(datetime.datetime.now()))
logging.info("======================================")
return JsonResponse.success()
# 获取一张图片 原理从opencv中读取一帧然后保存到本地
@app.route('/getImage')
def getImage():
logging.info("======================================")
logging.info("get Image start")
_, frame = cap.read() #从opencv读取一帧
cv2.imwrite("your_image_file_path111.jpg", frame) #把读取的一帧数据写入到本地图片中
return JsonResponse.success()
# 执行web服务, 端口号可自行修订
logging.info("start to run camera app, current_time: " + str(datetime.datetime.now()))
# port 可以更改指定端口号
app.run(host='0.0.0.0', port=65432, debug=True, threaded=True)
5、运行代码
进入Python虚拟环境,执行如下命令:
python HikRobotCamera.py
6、功能验证
1)开始预览
可以将 http://127.0.0.1:65432/startPreview 在前端用 img 标签 显示视频的实时预览效果。
http://127.0.0.1:65432/startPreview
2)停止预览
由于使用的这款海康机器人工业相机(MV-CS050-10GC)只能创建一个连接,所以,当预览完实时视频,需要调用该接口释放相机资源,避免资源被长期占用。
http://127.0.0.1:65432/stopPreview
3)获取图片
http://127.0.0.1:65432/getImage
查看保存到本地的图片
7、运行效果
原理其实很简单既然拍照的时候跟实时预览时都会占用相机 那就从实时预览的视频流中取一帧数据以图片的形式保存到本地就可以了