Skip to content

Commit 7ad06e0

Browse files
committed
direct init cam
1 parent 75f35cb commit 7ad06e0

File tree

2 files changed

+123
-84
lines changed

2 files changed

+123
-84
lines changed

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include requirements.txt hik_camera/MvCameraNode-CH.csv README.md

hik_camera/hik_camera.py

+122-84
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,101 @@
2020
)
2121

2222

23+
def get_host_ip_by_target_ip(target_ip):
24+
import socket
25+
26+
return [
27+
(s.connect((target_ip, 80)), s.getsockname()[0], s.close())
28+
for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]
29+
][0][1]
30+
31+
32+
def get_setting_df():
33+
csv = boxx.pd.read_csv(__file__.replace("hik_camera.py", "MvCameraNode-CH.csv"))
34+
setting_df = boxx.pd.DataFrame()
35+
36+
def to_key(key):
37+
if "[" in key:
38+
key = key[: key.index("[")]
39+
return key.strip()
40+
41+
def get_depend(key):
42+
key = key.strip()
43+
if "[" in key:
44+
return key[key.index("[") + 1 : -1]
45+
return ""
46+
47+
setting_df["key"] = csv[list(csv)[1]].map(to_key)
48+
setting_df["depend"] = csv[list(csv)[1]].map(get_depend)
49+
setting_df["dtype"] = csv[list(csv)[2]].map(lambda x: x.strip().lower())
50+
return setting_df
51+
52+
2353
class HikCamera(hik.MvCamera):
24-
def __init__(self):
54+
def __init__(self, ip=None, host_ip=None):
2555
super().__init__()
26-
self.get_setting_df()
56+
if ip is None:
57+
return
58+
ip = self.get_all_ips()[0]
59+
if host_ip is None:
60+
host_ip = get_host_ip_by_target_ip(ip)
61+
self._ip = ip
62+
self.host_ip = host_ip
63+
# self.init_by_ip()
64+
self.init_by_enum()
65+
66+
def setting(self):
67+
self.set_exposure(250000)
68+
self.setitem("ExposureAuto", "Continuous")
69+
# self.adjust_auto_exposure()
70+
71+
self.pixel_format = "RGB8"
72+
self.pixel_format = "BayerGB12Packed"
73+
self.setitem("PixelFormat", self.pixel_format)
74+
75+
self.setitem("GevSCPD", 2000) # 包延时 ns
76+
77+
def init_by_spec_ip(self,):
78+
"""
79+
SDK 有 Bug, 调用完"枚举设备" 接口后, 再调用"无枚举连接相机" 会无法打开相机.
80+
暂时不能用
81+
"""
82+
stDevInfo = hik.MV_CC_DEVICE_INFO()
83+
stGigEDev = hik.MV_GIGE_DEVICE_INFO()
84+
85+
stGigEDev.nCurrentIp = ip_to_int(self.ip)
86+
stGigEDev.nNetExport = ip_to_int(self.host_ip)
87+
stDevInfo.nTLayerType = hik.MV_GIGE_DEVICE
88+
stDevInfo.SpecialInfo.stGigEInfo = stGigEDev
89+
assert not self.MV_CC_CreateHandle(stDevInfo)
90+
91+
def init_by_enum(self):
92+
stDevInfo = self.get_dev_info(self.ip)
93+
assert not self.MV_CC_CreateHandle(stDevInfo)
94+
95+
@classmethod
96+
def get_dev_info(cls, ip=None):
97+
if not hasattr(cls, "ip_to_dev_info"):
98+
ip_to_dev_info = {}
99+
deviceList = hik.MV_CC_DEVICE_INFO_LIST()
100+
tlayerType = hik.MV_GIGE_DEVICE # | MV_USB_DEVICE
101+
assert not hik.MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
102+
for i in range(0, deviceList.nDeviceNum):
103+
mvcc_dev_info = cast(
104+
deviceList.pDeviceInfo[i], POINTER(hik.MV_CC_DEVICE_INFO)
105+
).contents
106+
_ip = int_to_ip(mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp)
107+
if mvcc_dev_info.nTLayerType == hik.MV_GIGE_DEVICE:
108+
ip_to_dev_info[_ip] = mvcc_dev_info
109+
cls.ip_to_dev_info = {
110+
ip: ip_to_dev_info[ip] for ip in sorted(ip_to_dev_info)
111+
}
112+
if ip is None:
113+
return cls.ip_to_dev_info
114+
return cls.ip_to_dev_info[ip]
27115

28116
high_speed_lock = Lock()
117+
setting_df = get_setting_df()
29118

30119
def get_frame(self):
31120
stFrameInfo = self.stFrameInfo
@@ -65,25 +154,6 @@ def get_frame(self):
65154
)
66155
return img
67156

68-
def get_setting_df(self):
69-
csv = boxx.pd.read_csv(__file__.replace("hik_camera.py", "MvCameraNode-CH.csv"))
70-
self.setting_df = boxx.pd.DataFrame()
71-
72-
def to_key(key):
73-
if "[" in key:
74-
key = key[: key.index("[")]
75-
return key.strip()
76-
77-
def get_depend(key):
78-
key = key.strip()
79-
if "[" in key:
80-
return key[key.index("[") + 1 : -1]
81-
return ""
82-
83-
self.setting_df["key"] = csv[list(csv)[1]].map(to_key)
84-
self.setting_df["depend"] = csv[list(csv)[1]].map(get_depend)
85-
self.setting_df["dtype"] = csv[list(csv)[2]].map(lambda x: x.strip().lower())
86-
87157
def getitem(self, key):
88158
df = self.setting_df
89159
dtype = df[df.key == key]["dtype"].iloc[0]
@@ -150,25 +220,6 @@ def adjust_auto_exposure(self, t=2):
150220
finally:
151221
self.MV_CC_StopGrabbing()
152222

153-
pixel_format_values = {
154-
"RGB8": 0x02180014,
155-
"BayerGB8": 0x0108000A,
156-
"BayerGB12": 0x01100012,
157-
"BayerGB12Packed": 0x010C002C,
158-
}
159-
160-
def setting(self):
161-
# self.adjust_auto_exposure()
162-
self.setitem("ExposureAuto", "Off")
163-
self.setitem("ExposureTime", 250000)
164-
self.setitem("ExposureAuto", "Continuous")
165-
166-
self.pixel_format = "RGB8"
167-
self.pixel_format = "BayerGB12Packed"
168-
self.setitem("PixelFormat", self.pixel_format_values[self.pixel_format])
169-
170-
self.setitem("GevSCPD", 2000) # 包延时 ns
171-
172223
def __enter__(self):
173224
assert not self.MV_CC_OpenDevice(hik.MV_ACCESS_Exclusive, 0)
174225

@@ -207,45 +258,25 @@ def get_shape(self):
207258
def __exit__(self, *l):
208259
self.MV_CC_CloseDevice()
209260

210-
@staticmethod
211-
def get_all_ips():
212-
deviceList = hik.MV_CC_DEVICE_INFO_LIST()
213-
tlayerType = hik.MV_GIGE_DEVICE # | MV_USB_DEVICE
214-
215-
# ch:枚举设备 | en:Enum device
216-
assert not hik.MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
217-
ips = {}
218-
for i in range(0, deviceList.nDeviceNum):
219-
mvcc_dev_info = cast(
220-
deviceList.pDeviceInfo[i], POINTER(hik.MV_CC_DEVICE_INFO)
221-
).contents
222-
if mvcc_dev_info.nTLayerType == hik.MV_GIGE_DEVICE:
223-
ips[int_to_ip(mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp)] = i
224-
return ips
261+
@classmethod
262+
def get_all_ips(cls):
263+
ip_to_dev_info = cls.get_dev_info()
264+
return sorted(ip_to_dev_info)
225265

226266
@classmethod
227-
def get_all_cams(cls):
228-
deviceList = hik.MV_CC_DEVICE_INFO_LIST()
229-
tlayerType = hik.MV_GIGE_DEVICE # | MV_USB_DEVICE
230-
231-
# ch:枚举设备 | en:Enum device
232-
assert not hik.MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
233-
cams = MultiHikCamera()
234-
for i in range(0, deviceList.nDeviceNum):
235-
mvcc_dev_info = cast(
236-
deviceList.pDeviceInfo[i], POINTER(hik.MV_CC_DEVICE_INFO)
237-
).contents
238-
if mvcc_dev_info.nTLayerType == hik.MV_GIGE_DEVICE:
239-
cam = cls()
240-
assert not cam.MV_CC_CreateHandle(mvcc_dev_info)
241-
ip = cam.ip
242-
cams[ip] = cam
243-
cams = MultiHikCamera({ip: cams[ip] for ip in sorted(cams)})
267+
def get_cams(cls, ips=None):
268+
if ips is None:
269+
ips = cls.get_all_ips()
270+
else:
271+
ips = sorted(ips)
272+
cams = MultiHikCamera({ip: cls(ip) for ip in ips})
244273
return cams
245274

275+
get_all_cams = get_cams
276+
246277
def MV_CC_CreateHandle(self, mvcc_dev_info):
247278
self.mvcc_dev_info = mvcc_dev_info
248-
self.ip = int_to_ip(mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp)
279+
self._ip = int_to_ip(mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp)
249280
assert not super().MV_CC_CreateHandle(mvcc_dev_info)
250281

251282
def __del__(self):
@@ -269,9 +300,18 @@ def raw_to_uint8_rgb(self, raw, poww=1, demosaicing_method="Malvar2004"):
269300
def is_raw(self):
270301
return "Bayer" in self.__dict__.get("pixel_format", "RGB8")
271302

303+
@property
304+
def ip(self):
305+
if not hasattr(self, "_ip"):
306+
self._ip = self.getitem("GevCurrentIPAddress")
307+
return self._ip
308+
272309

273310
class MultiHikCamera(dict):
274311
def __getattr__(self, attr):
312+
if not callable(getattr(next(iter(self.values())), attr)):
313+
return {k: getattr(cam, attr) for k, v in self.items()}
314+
275315
def func(*args, **kwargs):
276316
threads = []
277317
res = {}
@@ -304,25 +344,23 @@ def __exit__(self, *l):
304344
ips = HikCamera.get_all_ips()
305345
print(ips)
306346
ip = list(ips)[0]
307-
cams = HikCamera.get_all_cams()
308-
cam = cams.get("10.9.5.102", cams[ip])
309-
with cams:
310-
with boxx.timeit("get_frame"):
311-
imgs = cams.get_frame()
312-
print("imgs = cams.get_frame()")
313-
boxx.tree(imgs)
314-
# rgbs = [cam.raw_to_uint8_rgb(raw, poww=.3, demosaicing_method="simple") for raw in imgs.values()]
315-
# normas = [norma(img) for img in imgs.values()]
316-
# shows-[normas, rgbs]
317347

348+
cam = HikCamera(ip)
349+
with cam:
318350
for i in range(2):
319351
with boxx.timeit("cam.get_frame"):
320352
img = cam.get_frame()
321353
print("cam.get_exposure", cam["ExposureTime"])
322-
boxx.show(img)
323354
if cam.is_raw:
324355
rgbs = [
325356
cam.raw_to_uint8_rgb(img, poww=1),
326357
cam.raw_to_uint8_rgb(img, poww=0.3),
327358
]
328359
boxx.show(rgbs)
360+
361+
cams = HikCamera.get_all_cams()
362+
with cams:
363+
with boxx.timeit("cams.get_frame"):
364+
imgs = cams.get_frame()
365+
print("imgs = cams.get_frame()")
366+
boxx.tree(imgs)

0 commit comments

Comments
 (0)