一、前期准备
1、python环境搭建
2、安装MVS软件
3、网上博客参考
1)RTSP(Runtime Stream Protocol)协议方向
(很遗憾,此路不通!!!)
因为我们用的 海康机器人工业相机 MV-CU060-10GM 这款相机,不支持 RTSP 协议。
如下博客适用于 海康威视摄像头,并不适用于 海康工业相机,如果是使用海康威视摄像头的小伙伴可以参考下。
参考博客:海康威视摄像头对接SDK实时预览功能和抓拍功能,懒癌福利,可直接CV
2)Java实现方向
(不能完全满足客户需求,此路不全通!!!)
使用Java目前参考官网的示例,实现了图片抓取,并上传的功能,但是没有实现视频流的实时获取和显示的功能。
如果需求只是获取图片,不要求视频流实时显示,可以通过Java就可以实现。
3)Python实现方向
(目前,网上没有直接能完全满足上述三个需求的,本人通过借鉴、整合,结合Flask框架实现的。)
参考博客如下:
python语言下使用opencv接口cv2.VideoCapture()接口调用海康机器人工业相机 (此篇博文可以重点看!!!)
通过python调用海康威视工业摄像头并进行图像存储,同时使用opencv实时图像显示(数据流问题已解决)
python调用海康工业相机并用opencv显示(整体实现)(此篇博文可以重点看!!!)
pyQT5 学习使用 笔记 六 pyQt5+opencv 显示海康GIGE相机动态视频流 (该方式虽然实现了视频的实时显示,但是,无法被给前端直接调用)
web实时显示摄像头图像(python) (此篇博文可以重点看!!!)
4)Flask 的相关教程和博客
https://www.w3cschool.cn/flask/
https://dormousehole.readthedocs.io/en/latest/
https://blog.csdn.net/weixin_44239541/article/details/89390139
https://zhuanlan.zhihu.com/p/104273184
https://blog.csdn.net/tulan_xiaoxin/article/details/79132214
二、Python 代码实现
1、测试代码
1)抓取图片测试代码
前提条件:将 *
C:\Program Files (x86)\MVS\Development\Samples\Python*
目录下的
MvImport
目录,copy到自己的工程目录下,创建测试文件 TestGrabImage.py
代码如下:
# -- coding: utf-8 --
import cv2
import sys
import copy
import msvcrt
import numpy as np
from ctypes import *
sys.path.append("./MvImport")
from MvCameraControl_class import *
if __name__ == "__main__":
deviceList = MV_CC_DEVICE_INFO_LIST()
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
# ch:枚举设备 | en:Enum device
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
if ret != 0:
print ("enum devices fail! ret[0x%x]" % ret)
sys.exit()
if deviceList.nDeviceNum == 0:
print ("find no device!")
sys.exit()
print ("find %d devices!" % deviceList.nDeviceNum)
for i in range(0, deviceList.nDeviceNum):
mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
print ("\ngige device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8)
nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
print ("current ip: %d.%d.%d.%d\n" % (nip1, nip2, nip3, nip4))
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
print ("\nu3v device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
if per == 0:
break
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print ("user serial number: %s" % strSerialNumber)
nConnectionNum = 0
if int(nConnectionNum) >= deviceList.nDeviceNum:
print ("intput error!")
sys.exit()
# ch:创建相机实例 | en:Creat Camera Object
cam = MvCamera()
# ch:选择设备并创建句柄 | en:Select device and create handle
stDeviceList = cast(deviceList.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents
ret = cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print ("create handle fail! ret[0x%x]" % ret)
sys.exit()
# ch:打开设备 | en:Open device
ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
print ("open device fail! ret[0x%x]" % ret)
sys.exit()
# ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
nPacketSize = cam.MV_CC_GetOptimalPacketSize()
if int(nPacketSize) > 0:
ret = cam.MV_CC_SetIntValue("GevSCPSPacketSize", nPacketSize)
if ret != 0:
print ("Warning: Set Packet Size fail! ret[0x%x]" % ret)
else:
print ("Warning: Get Packet Size fail! ret[0x%x]" % nPacketSize)
# ch:设置触发模式为off | en:Set trigger mode as off
ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
if ret != 0:
print ("set trigger mode fail! ret[0x%x]" % ret)
sys.exit()
# ch:获取数据包大小 | en:Get payload size
stParam = MVCC_INTVALUE()
memset(byref(stParam), 0, sizeof(MVCC_INTVALUE))
ret = cam.MV_CC_GetIntValue("PayloadSize", stParam)
if ret != 0:
print ("get payload size fail! ret[0x%x]" % ret)
sys.exit()
nPayloadSize = stParam.nCurValue
# ch:开始取流 | en:Start grab image
ret = cam.MV_CC_StartGrabbing()
if ret != 0:
print ("start grabbing fail! ret[0x%x]" % ret)
sys.exit()
stDeviceList = MV_FRAME_OUT_INFO_EX()
memset(byref(stDeviceList), 0, sizeof(stDeviceList))
data_buf = (c_ubyte * nPayloadSize)()
ret = cam.MV_CC_GetOneFrameTimeout(byref(data_buf), nPayloadSize, stDeviceList, 1000)
if ret == 0:
print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stDeviceList.nWidth, stDeviceList.nHeight, stDeviceList.nFrameNum))
nRGBSize = stDeviceList.nWidth * stDeviceList.nHeight * 3
stConvertParam=MV_SAVE_IMAGE_PARAM_EX()
stConvertParam.nWidth = stDeviceList.nWidth
stConvertParam.nHeight = stDeviceList.nHeight
stConvertParam.pData = data_buf
stConvertParam.nDataLen = stDeviceList.nFrameLen
stConvertParam.enPixelType = stDeviceList.enPixelType
stConvertParam.nImageLen = stConvertParam.nDataLen
stConvertParam.nJpgQuality = 70
stConvertParam.enImageType = MV_Image_Jpeg
stConvertParam.pImageBuffer = (c_ubyte * nRGBSize)()
stConvertParam.nBufferSize = nRGBSize
# ret = cam.MV_CC_ConvertPixelType(stConvertParam)
print(stConvertParam.nImageLen)
ret = cam.MV_CC_SaveImageEx2(stConvertParam)
if ret != 0:
print ("convert pixel fail ! ret[0x%x]" % ret)
del data_buf
sys.exit()
file_path = "AfterConvert_RGB2.jpg"
file_open = open(file_path.encode('ascii'), 'wb+')
img_buff = (c_ubyte * stConvertParam.nImageLen)()
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pImageBuffer, stConvertParam.nImageLen)
file_open.write(img_buff)
print ("Save Image succeed!")
# ch:停止取流 | en:Stop grab image
ret = cam.MV_CC_StopGrabbing()
if ret != 0:
print ("stop grabbing fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
# ch:关闭设备 | Close device
ret = cam.MV_CC_CloseDevice()
if ret != 0:
print ("close deivce fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
# ch:销毁句柄 | Destroy handle
ret = cam.MV_CC_DestroyHandle()
if ret != 0:
print ("destroy handle fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
del data_buf
2)Python+Qt 实现视频流实时显示测试代码
前提条件:将 *C:\Program Files (x86)\MVS\Development\Samples\Python* 目录下的 MvImport 目录,copy到自己的工程目录下,创建测试文件 TestVideoStream.py
代码如下:
# -- coding: utf-8 --
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import *
import numpy as np
#from CameraControl_header import MV_CC_DEVICE_INFO_LIST
#from mainWindow import Ui_MainWindow # 导入创建的GUI类
import sys
import threading
import msvcrt
from ctypes import *
sys.path.append("./MvImport")
from MvCameraControl_class import *
from Ui_MainWindow import *
from CameraParams_header import *
class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):
sendAddDeviceName = pyqtSignal() #定义一个添加设备列表的信号。
deviceList = MV_CC_DEVICE_INFO_LIST()
g_bExit = False
# ch:创建相机实例 | en:Creat Camera Object
cam = MvCamera()
def connect_and_emit_sendAddDeviceName(self):
# Connect the sendAddDeviceName signal to a slot.
self.sendAddDeviceName.connect(self.SelectDevice)
# Emit the signal.
self.sendAddDeviceName.emit()
def __init__(self):
super(mywindow, self).__init__()
self.setupUi(self)
self.connect_and_emit_sendAddDeviceName()
self.butopenCam.clicked.connect(lambda:self.openCam(self.camSelect.currentData()))
self.butcloseCam.clicked.connect(self.closeCam)
# setting main window geometry
desktop_geometry = QtWidgets.QApplication.desktop() # 获取屏幕大小
main_window_width = desktop_geometry.width() # 屏幕的宽
main_window_height = desktop_geometry.height() # 屏幕的高
rect = self.geometry() # 获取窗口界面大小
window_width = rect.width(