Merge remote-tracking branch 'origin/master'

This commit is contained in:
edo-neo 2025-01-21 10:52:23 +01:00
commit 8ec410c676
4 changed files with 361 additions and 41 deletions

View File

@ -0,0 +1,233 @@
import ctypes
import struct
from ctypes import *
import sys
MV_MAX_DEVICE_NUM=256
MV_VS_OK=0x00000000
CHUNK_MASK_IMAGE_PORT=60005536
CHUNK_RESULT_PORT=60005537
mv_lib = ctypes.windll.LoadLibrary("src/test/hikrobot_sc/bin/MvVisionSensorControl.dll")
# define structures
from ctypes import *
class MvVSGvspPixelType(c_int):
MVVS_PixelType_Undefined = 0xFFFFFFFF
MVVS_PixelType_Mono1p = (0x0037)
MVVS_PixelType_Mono2p = (0x0038)
MVVS_PixelType_Mono4p = (0x0039)
MVVS_PixelType_Mono8 = (0x0001)
MVVS_PixelType_Mono8_Signed = (0x0002)
MVVS_PixelType_Mono10 = (0x0003)
MVVS_PixelType_Mono10_Packed = (0x0004)
MVVS_PixelType_Mono12 = (0x0005)
MVVS_PixelType_Mono12_Packed = (0x0006)
MVVS_PixelType_Mono14 = (0x0025)
MVVS_PixelType_Mono16 = (0x0007)
MVVS_PixelType_BayerGR8 = (0x0008)
MVVS_PixelType_BayerRG8 = (0x0009)
MVVS_PixelType_BayerGB8 = (0x000A)
MVVS_PixelType_BayerBG8 = (0x000B)
MVVS_PixelType_BayerGR10 = (0x000C)
MVVS_PixelType_BayerRG10 = (0x000D)
MVVS_PixelType_BayerGB10 = (0x000E)
MVVS_PixelType_BayerBG10 = (0x000F)
MVVS_PixelType_BayerGR12 = (0x0010)
MVVS_PixelType_BayerRG12 = (0x0011)
MVVS_PixelType_BayerGB12 = (0x0012)
MVVS_PixelType_BayerBG12 = (0x0013)
MVVS_PixelType_BayerGR10_Packed = (0x0026)
MVVS_PixelType_BayerRG10_Packed = (0x0027)
MVVS_PixelType_BayerGB10_Packed = (0x0028)
MVVS_PixelType_BayerBG10_Packed = (0x0029)
MVVS_PixelType_BayerGR12_Packed = (0x002A)
MVVS_PixelType_BayerRG12_Packed = (0x002B)
MVVS_PixelType_BayerGB12_Packed = (0x002C)
MVVS_PixelType_BayerBG12_Packed = (0x002D)
MVVS_PixelType_BayerGR16 = (0x002E)
MVVS_PixelType_BayerRG16 = (0x002F)
MVVS_PixelType_BayerGB16 = (0x0030)
MVVS_PixelType_BayerBG16 = (0x0031)
MVVS_PixelType_RGB8_Packed = (0x0014)
MVVS_PixelType_BGR8_Packed = (0x0015)
MVVS_PixelType_RGBA8_Packed = (0x0016)
MVVS_PixelType_BGRA8_Packed = (0x0017)
MVVS_PixelType_RGB10_Packed = (0x0018)
MVVS_PixelType_BGR10_Packed = (0x0019)
MVVS_PixelType_RGB12_Packed = (0x001A)
MVVS_PixelType_BGR12_Packed = (0x001B)
MVVS_PixelType_RGB16_Packed = (0x0033)
MVVS_PixelType_BGR16_Packed = (0x004B)
MVVS_PixelType_RGBA16_Packed = (0x0064)
MVVS_PixelType_BGRA16_Packed = (0x0051)
MVVS_PixelType_RGB10V1_Packed = (0x001C)
MVVS_PixelType_RGB10V2_Packed = (0x001D)
MVVS_PixelType_RGB12V1_Packed = (0X0034)
MVVS_PixelType_RGB565_Packed = (0x0035)
MVVS_PixelType_BGR565_Packed = (0X0036)
MVVS_PixelType_YUV411_Packed = (0x001E)
MVVS_PixelType_YUV422_Packed = (0x001F)
MVVS_PixelType_YUV422_YUYV_Packed = (0x0032)
MVVS_PixelType_YUV444_Packed = (0x0020)
MVVS_PixelType_YCBCR8_CBYCR = (0x003A)
MVVS_PixelType_YCBCR422_8 = (0x003B)
MVVS_PixelType_YCBCR422_8_CBYCRY = (0x0043)
MVVS_PixelType_YCBCR411_8_CBYYCRYY = (0x003C)
MVVS_PixelType_YCBCR601_8_CBYCR = (0x003D)
MVVS_PixelType_YCBCR601_422_8 = (0x003E)
MVVS_PixelType_YCBCR601_422_8_CBYCRY = (0x0044)
MVVS_PixelType_YCBCR601_411_8_CBYYCRYY = (0x003F)
MVVS_PixelType_YCBCR709_8_CBYCR = (0x0040)
MVVS_PixelType_YCBCR709_422_8 = (0x0041)
MVVS_PixelType_YCBCR709_422_8_CBYCRY = (0x0045)
MVVS_PixelType_YCBCR709_411_8_CBYYCRYY = (0x0042)
MVVS_PixelType_RGB8_Planar = (0x0021)
MVVS_PixelType_RGB10_Planar = (0x0022)
MVVS_PixelType_RGB12_Planar = (0x0023)
MVVS_PixelType_RGB16_Planar = (0x0024)
MVVS_PixelType_Jpeg = (0x0001)
class MV_VS_DATA(Structure):
_fields_ = [
("pImage", POINTER(c_char)), # Pointer of Image
("nImageLen", c_uint), # The Length of Image
("nImageWidth", c_uint), # Image Width
("nImageHeight", c_uint), # Image Height
("nImageNum", c_uint64), # Image Number
("enPixelType", c_int), # Pixel Type (assuming MvVSGvspPixelType is an enum)
("nDevTimeStampHigh", c_uint), # Timestamp high 32 bits
("nDevTimeStampLow", c_uint), # Timestamp low 32 bits
("nReserved0", c_uint), # Reserved, 8-byte aligned
("nHostTimeStamp", c_int64), # Host-generated timestamp
("pChunkData", POINTER(c_char)), # Chunk data
("nChunkDataLen", c_uint), # Chunk Length
("nReserved", c_uint * 64), # Reserved
]
class MV_VS_DEVICE_INFO(ctypes.Structure):
_fields_ = [
("nMajorVer", ctypes.c_ushort), # GigE protocol Major Version
("nMinorVer", ctypes.c_ushort), # GigE protocol Minor Version
("nMacAddrHigh", ctypes.c_uint), # High MAC Address
("nMacAddrLow", ctypes.c_uint), # Low MAC Address
("nIpCfgOption", ctypes.c_uint), # Supported IP Configuration Options
("nIpCfgCurrent", ctypes.c_uint), # IP Configuration
("nCurrentIp", ctypes.c_uint), # Current IP
("nCurrentSubNetMask", ctypes.c_uint), # Current Subnet Mask
("nDefultGateWay", ctypes.c_uint), # Current Gateway
("chManufacturerName", ctypes.c_char * 32), # Manufacturer Name
("chModelName", ctypes.c_char * 32), # Model Name
("chDeviceVersion", ctypes.c_char * 32), # Device Version
("chManufacturerSpecificInfo", ctypes.c_char * 48), # Manufacturer Specific Info
("chSerialNumber", ctypes.c_char * 16), # Serial Number
("chUserDefinedName", ctypes.c_char * 16), # User Defined Name
("nNetExport", ctypes.c_uint), # IP address of connected network port
("nReserved", ctypes.c_uint * 8), # Reserved
]
class MV_VS_DEVICE_INFO_LIST(ctypes.Structure):
_fields_ = [
("nDeviceNum", ctypes.c_uint), # Online Device Number
("pDeviceInfo", ctypes.POINTER(MV_VS_DEVICE_INFO) * MV_MAX_DEVICE_NUM), # Device info array
]
# Define function signatures
mv_lib.MV_VS_GetResultData.argtypes = [c_void_p, POINTER(MV_VS_DATA), c_int]
mv_lib.MV_VS_GetResultData.restype = c_int
mv_lib.MV_VS_ReleaseResultData.argtypes = [ctypes.c_void_p, ctypes.POINTER(MV_VS_DATA)]
mv_lib.MV_VS_ReleaseResultData.restype = ctypes.c_int
mv_lib.MV_VS_EnumDevices.argtypes = [POINTER(MV_VS_DEVICE_INFO_LIST)]
mv_lib.MV_VS_EnumDevices.restype = c_int
mv_lib.MV_VS_CreateHandle.argtypes = [POINTER(c_void_p), c_void_p] # Assuming pHandle is a void* and pstDeviceInfo is a struct
mv_lib.MV_VS_CreateHandle.restype = c_int
mv_lib.MV_VS_Login.argtypes = [c_void_p, c_char_p, c_char_p]
mv_lib.MV_VS_Login.restype = c_int
mv_lib.MV_VS_SetBoolValue.argtypes = [c_void_p, c_char_p, c_bool]
mv_lib.MV_VS_SetBoolValue.restype = c_int
mv_lib.MV_VS_SetEnumValue.argtypes = [c_void_p, c_char_p, c_uint]
mv_lib.MV_VS_SetEnumValue.restype = c_int
mv_lib.MV_VS_StartRun.argtypes = [c_void_p] # handle
mv_lib.MV_VS_StartRun.restype = c_int
def MV_VS_GetFrame(handle):
nRet = MV_VS_OK
stFrameData = MV_VS_DATA()
nRet = mv_lib.MV_VS_GetResultData(handle, byref(stFrameData), 2000)
if nRet == MV_VS_OK:
# Print frame information
print(
f"Frame Width: [{stFrameData.nImageWidth}], Height: [{stFrameData.nImageHeight}], ImageLen: [{stFrameData.nImageLen}]")
# Process chunk data
currentDataTag = 0
while stFrameData.nChunkDataLen > currentDataTag:
chunkLength = \
struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 4 - currentDataTag)[0]
chunkID = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - currentDataTag)[
0]
print(f"chunkLength [{chunkLength}], chunkID: [{chunkID}]")
if chunkLength <= 0 or chunkLength > stFrameData.nChunkDataLen - 8 - currentDataTag:
# Handle exception
break
if chunkID == CHUNK_RESULT_PORT: # Result data in JSON format
chResultInfo = ctypes.cast(
stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag),
ctypes.POINTER(ctypes.c_char))
print(f"chResultInfo [{chResultInfo.value.decode()}] end")
elif chunkID == CHUNK_MASK_IMAGE_PORT: # Mask image data
maskModID = struct.unpack_from("<I", stFrameData.pChunkData,
stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag)[0]
maskModFormat = struct.unpack_from("<I", stFrameData.pChunkData,
stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 4)[0]
maskModWidth = struct.unpack_from("<I", stFrameData.pChunkData,
stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 8)[0]
maskModHeight = struct.unpack_from("<I", stFrameData.pChunkData,
stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 12)[0]
print(
f"Mask ModID[{maskModID}], ModFormat[{maskModFormat}], ModWidth[{maskModWidth}], ModHeight[{maskModHeight}], ")
chMaskModImageData = ctypes.cast(
stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 16),
ctypes.POINTER(ctypes.c_char))
print(f"Mask data length [{chunkLength - 16}]")
currentDataTag += 8 + chunkLength
else:
print(f"Get frame buffer fail! nRet [0x{nRet:x}]")
# Release frame buffer
nRet = mv_lib.MV_VS_ReleaseResultData(handle, ctypes.byref(stFrameData))
if nRet != MV_VS_OK:
print(f"Release frame buffer fail! nRet [0x{nRet:x}]")
else:
print(f"MV_VS_GetResultData fail! nRet [0x{nRet & 0xFFFFFFFF:x}]")

View File

@ -0,0 +1,74 @@
import ctypes
import struct
from ctypes import *
import sys
from PyQt5.QtCore import pyqtSignal, QMutex
from components.component import Component
from hikrobot_dll import *
class HikrobotSmartCamera(Component):
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True, num_cameras=1):
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.lock = QMutex()
self.simulate = "--sim-camera" in sys.argv
self.num_cameras=num_cameras
self.lib=mv_lib
def config_changed(self):
self.lib.MV_VS_DEVICE_INFO_LIST()
for cam_idx in range(self.num_cameras):
pass
@Component.reconfig_on_error
def _get(self):
frame = None
super()._get([frame])
def GetFrame(self,handle):
nRet = MV_VS_OK
stFrameData = MV_VS_DATA()
while True:
nRet = self.lib.MV_VS_GetResultData(handle, ctypes.byref(stFrameData), 1000)
if nRet == MV_VS_OK:
# Print frame information
print(f"Frame Width: [{stFrameData.nImageWidth}], Height: [{stFrameData.nImageHeight}], ImageLen: [{stFrameData.nImageLen}]")
# Process chunk data
currentDataTag = 0
while stFrameData.nChunkDataLen > currentDataTag:
chunkLength = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 4 - currentDataTag)[0]
chunkID = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - currentDataTag)[0]
print(f"chunkLength [{chunkLength}], chunkID: [{chunkID}]")
if chunkLength <= 0 or chunkLength > stFrameData.nChunkDataLen - 8 - currentDataTag:
# Handle exception
break
if chunkID == CHUNK_RESULT_PORT: # Result data in JSON format
chResultInfo = ctypes.cast(stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag), ctypes.POINTER(ctypes.c_char))
print(f"chResultInfo [{chResultInfo.value.decode()}] end")
elif chunkID == CHUNK_MASK_IMAGE_PORT: # Mask image data
maskModID = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag)[0]
maskModFormat = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 4)[0]
maskModWidth = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 8)[0]
maskModHeight = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 12)[0]
print(f"Mask ModID[{maskModID}], ModFormat[{maskModFormat}], ModWidth[{maskModWidth}], ModHeight[{maskModHeight}], ")
chMaskModImageData = ctypes.cast(stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 16), ctypes.POINTER(ctypes.c_char))
print(f"Mask data length [{chunkLength - 16}]")
currentDataTag += 8 + chunkLength
# Release frame buffer
nRet = self.lib.MV_VS_ReleaseResultData(handle, ctypes.byref(stFrameData))
if nRet != MV_VS_OK:
print(f"Release frame buffer fail! nRet [0x{nRet:x}]")
else:
print(f"Get frame buffer fail! nRet [0x{nRet:x}]")

View File

@ -1,48 +1,11 @@
import ctypes import ctypes
import os import os
import time
from ctypes import *
# Load the MvVisionSensorControl library from src.components.hikrobot_dll import *
mv_lib = ctypes.windll.LoadLibrary("bin/MvVisionSensorControl.dll")
MV_MAX_DEVICE_NUM=256
# Define the necessary structures and constants from MvVisionSensorDefine.h # Define the necessary structures and constants from MvVisionSensorDefine.h
class MV_VS_DEVICE_INFO(ctypes.Structure):
_fields_ = [
("nMajorVer", ctypes.c_ushort), # GigE protocol Major Version
("nMinorVer", ctypes.c_ushort), # GigE protocol Minor Version
("nMacAddrHigh", ctypes.c_uint), # High MAC Address
("nMacAddrLow", ctypes.c_uint), # Low MAC Address
("nIpCfgOption", ctypes.c_uint), # Supported IP Configuration Options
("nIpCfgCurrent", ctypes.c_uint), # IP Configuration
("nCurrentIp", ctypes.c_uint), # Current IP
("nCurrentSubNetMask", ctypes.c_uint), # Current Subnet Mask
("nDefultGateWay", ctypes.c_uint), # Current Gateway
("chManufacturerName", ctypes.c_char * 32), # Manufacturer Name
("chModelName", ctypes.c_char * 32), # Model Name
("chDeviceVersion", ctypes.c_char * 32), # Device Version
("chManufacturerSpecificInfo", ctypes.c_char * 48), # Manufacturer Specific Info
("chSerialNumber", ctypes.c_char * 16), # Serial Number
("chUserDefinedName", ctypes.c_char * 16), # User Defined Name
("nNetExport", ctypes.c_uint), # IP address of connected network port
("nReserved", ctypes.c_uint * 8), # Reserved
]
MV_MAX_DEVICE_NUM = 256 # Maximum number of supported devices
class MV_VS_DEVICE_INFO_LIST(ctypes.Structure):
_fields_ = [
("nDeviceNum", ctypes.c_uint), # Online Device Number
("pDeviceInfo", ctypes.POINTER(MV_VS_DEVICE_INFO) * MV_MAX_DEVICE_NUM), # Device info array
]
# Define MV_VS_OK from MvVSErrorDefine.h (assuming it's 0)
MV_VS_OK = 0
# Define function signatures
mv_lib.MV_VS_EnumDevices.argtypes = [ctypes.POINTER(MV_VS_DEVICE_INFO_LIST)]
mv_lib.MV_VS_EnumDevices.restype = ctypes.c_int
def print_device_info(device_info_list): def print_device_info(device_info_list):
num_devices=device_info_list.nDeviceNum num_devices=device_info_list.nDeviceNum
@ -57,6 +20,7 @@ def print_device_info(device_info_list):
def main(): def main():
global MV_VS_OK
print("SC2016 TEST") print("SC2016 TEST")
device_info_list = MV_VS_DEVICE_INFO_LIST() device_info_list = MV_VS_DEVICE_INFO_LIST()
@ -75,6 +39,56 @@ def main():
print("Find No Devices!") print("Find No Devices!")
return -2 return -2
if device_info_list.nDeviceNum == 2:
print("Starting dual camera test!")
# Define MV_VS_OK (replace with the actual value)
MV_VS_OK = 0
MV_VS_DEVICE_INFO_1 = device_info_list.pDeviceInfo[0];
MV_VS_DEVICE_INFO_2 = device_info_list.pDeviceInfo[1];
pHandle1 = c_void_p()
pHandle2 = c_void_p()
nRet1 = mv_lib.MV_VS_CreateHandle(byref(pHandle1), MV_VS_DEVICE_INFO_1)
nRet2 = mv_lib.MV_VS_CreateHandle(byref(pHandle2), MV_VS_DEVICE_INFO_2)
if nRet1 != MV_VS_OK or nRet2 != MV_VS_OK:
print(f"Create Handle failed! [{nRet1:#x} {nRet2:#x}]")
return
nRet1 = mv_lib.MV_VS_Login(pHandle1, b"Admin", b"Abc1234")
nRet2 = mv_lib.MV_VS_Login(pHandle2, b"Admin", b"Abc1234")
if nRet1 != MV_VS_OK or nRet2 != MV_VS_OK:
print(f"Login failed! [{nRet1:#x} {nRet2:#x}]")
return
else:
print("Login OK")
nRet1 = mv_lib.MV_VS_SetBoolValue(pHandle1, b"CommandImageMode", 0)
nRet2 = mv_lib.MV_VS_SetBoolValue(pHandle2, b"CommandImageMode", 0)
if nRet1 != MV_VS_OK or nRet2 != MV_VS_OK:
print(f"CommandImageMode failed! [{nRet1 & 0xFFFFFFFF:#x} {nRet2 & 0xFFFFFFFF:#x}]")
return
else:
print("CommandImageMode OK")
nRet1 = mv_lib.MV_VS_SetEnumValue(pHandle1, b"AcquisitionMode", 2)
nRet2 = mv_lib.MV_VS_SetEnumValue(pHandle2, b"AcquisitionMode", 2)
if nRet1 != MV_VS_OK or nRet2 != MV_VS_OK:
print(f"AcquisitionMode failed! [{nRet1 & 0xFFFFFFFF:#x} {nRet2 & 0xFFFFFFFF:#x}]")
return
else:
print("AcquisitionMode OK")
nRet1 = mv_lib.MV_VS_StartRun(pHandle1)
nRet2 = mv_lib.MV_VS_StartRun(pHandle2)
time.sleep(1)
if nRet1 != MV_VS_OK or nRet2 != MV_VS_OK:
print(f"Start run failed! [{nRet1&0xFFFFFFFF:#x} {nRet2&0xFFFFFFFF:#x}]")
return
else:
print("Start run OK")
MV_VS_GetFrame(pHandle1)
MV_VS_GetFrame(pHandle2)
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -6,7 +6,6 @@ import weakref
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PyQt5.QtCore import QTimer, pyqtSlot from PyQt5.QtCore import QTimer, pyqtSlot
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from component import Component
from lib.db import Archive, Recipes, Users from lib.db import Archive, Recipes, Users
from lib.helpers import get_shift from lib.helpers import get_shift
from lib.helpers.step import Step from lib.helpers.step import Step