目前缺芯的大环境也影响到工业相机上面了,使用支持国产海康机器人的工业相机进行视觉开发是不错的替代方案。价格交期很是感人呐!
参考文章python调用海康工业相机并用opencv显示(整体实现)
博主写的很全面非常好。
PyQt显示相机图像本文推荐另一种方法“将numpy array 先转化为 Pillow image 再转化为Pixmap” 并用来显示。
主要步骤:
(1)HikRobot 官网下载安装“机器视觉工业相机客户端MVS V3.3.1(Windows)”, 下载链接。
(2)安装后参考官网自带的Python demo, 默认安装文件夹为C:\Program Files (x86)\MVS\Development\Samples\Python
(3)下面的代码设置了相机的曝光时间、外触发Line0,以及查看曝光时间。另外外触发使用1.5V干电池触发没有反映,3V干电池就可以了。
后面就自己在UI里面增加控制相机和按钮了,多相机同样如此。
博主QQ 562604218 欢迎沟通交流。
import threading
from datetime import datetime
import cv2
import numpy as np
from PIL import Image
from PyQt5 import QtCore
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QLabel, QApplication, QWidget
from PyQt5.QtCore import Qt
from MvCameraControl_class import *
class Mainwindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setObjectName("MainWindow")
self.resize(800, 600)
self.label1 = QLabel(self)
self.label1.setAlignment(Qt.AlignCenter)
self.label1.setGeometry(QtCore.QRect(70, 70, 561, 451))
def closeEvent(self, event) -> None:
# close camera
# ch:停止取流 | en:Stop grab image
ret = cam.MV_CC_StopGrabbing()
if ret != 0:
print("stop grabbing fail! ret[0x%x]" % ret)
sys.exit()
# ch:关闭设备 | Close device
ret = cam.MV_CC_CloseDevice()
if ret != 0:
print("close deivce fail! ret[0x%x]" % ret)
sys.exit()
# ch:销毁句柄 | Destroy handle
ret = cam.MV_CC_DestroyHandle()
if ret != 0:
print("destroy handle fail! ret[0x%x]" % ret)
sys.exit()
event.accept() # close app
print('Exit success')
class Getimage_save(threading.Thread):
def __init__(self):
super(Getimage_save, self).__init__()
def run(self) -> None:
stOutFrame = MV_FRAME_OUT()
memset(byref(stOutFrame), 0, sizeof(stOutFrame))
while True:
ret = cam.MV_CC_GetImageBuffer(stOutFrame, 10000000)
if None != stOutFrame.pBufAddr and 0 == ret:
print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (
stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))
pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()
cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,
stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)
data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),
dtype=np.uint8)
# image numpy array
image = data.reshape((stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth))
print('image shape:', image.shape)
# image_show = QImage(image, stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, QImage.Format_Indexed8)
# 显示图片
h, w = main.label1.height(), main.label1.width()
# 方式一 将numpy array 先转化为 Pillow image 再转化为Pixmap
frame = Image.fromarray(image).toqpixmap().scaled(w, h)
# 方式二 将numpy array 先转化为 QImage 再转化为Pixmap, 灰度图使用image.copy()
# RGB picture
#h, w = window.current_image_lb.height(), window.current_image_lb.width()
#qimage = QImage(img, img.shape[1], img.shape[0], 3*img.shape[1], QImage.Format_RGB888)
#frame = QPixmap.fromImage(qimage).scaled(w, h)
# image_show = QImage(image.copy(), stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight,
# QImage.Format_Indexed8)
# frame = QPixmap.fromImage(image_show).scaled(w, h)
# GUI 显示图片
main.label1.setPixmap(frame)
now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
if not os.path.exists(f'C:/Packing_pic/{now[0:10]}'):
os.makedirs(f'C:/Packing_pic/{now[0:10]}', exist_ok=True)
cv2.imwrite(f"C:/Packing_pic/{now[0:10]}/{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.jpeg", image)
# 将 pstFrame 内的数据指针权限进行释放
cam.MV_CC_FreeImageBuffer(stOutFrame)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Mainwindow()
main.show()
deviceList = MV_CC_DEVICE_INFO_LIST()
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
# ch:枚举设备 | en:Enum device
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
print("Find %d devices!" % deviceList.nDeviceNum)
cam_dict = {}
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_USB_DEVICE: # USB camera
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print("user serial number: %s" % strSerialNumber)
cam_dict[strSerialNumber] = i
cam_sn = ['00E53763769']
# ch:创建相机实例 | en:Creat Camera Object
cam = MvCamera()
# ch:选择设备并创建句柄 | en:Select device and create handle
stDeviceList = cast(deviceList.pDeviceInfo[cam_dict[cam_sn[0]]], 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:设置触发模式为on, 硬件触发 | en:Set trigger mode as on
cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_ON)
# set Exposure_time
cam.MV_CC_SetFloatValue("ExposureTime", 500.0)
# get Exposure_time
stFloatValue = MVCC_FLOATVALUE()
memset(byref(stFloatValue), 0, sizeof(MVCC_FLOATVALUE))
cam.MV_CC_GetFloatValue("ExposureTime", stFloatValue)
print('Exposure_time:', stFloatValue.fCurValue)
# set triggersource line0
cam.MV_CC_SetEnumValue("TriggerSource", MV_TRIGGER_SOURCE_LINE0)
# ch:开始取流 | en:Start grab image
cam.MV_CC_StartGrabbing()
save_pic = Getimage_save()
save_pic.setDaemon(True)
save_pic.start()
sys.exit(app.exec_())
效果图: