taotoolkit 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1186 @@
1
+ # -*- coding: utf-8 -*-
2
+ # @Time : 2024/1/4
3
+ # @Author : taotaoli
4
+ # @File : camDvt.py
5
+
6
+ import os
7
+ import sys
8
+ import argparse
9
+ import time
10
+ import re
11
+ from . import asrVrf
12
+ import math
13
+ import numpy as np
14
+ from matplotlib import pyplot as plt
15
+
16
+ from .tao_common import (
17
+ debugCtrl,
18
+ pCmd,
19
+ is_number,
20
+ loge,
21
+ logi,
22
+ renameFile,
23
+ normalize_args,
24
+ register_command,
25
+ )
26
+
27
+ from .tao_tuning import (
28
+ asrCamOp,
29
+ )
30
+
31
+ plt.set_loglevel("INFO")
32
+
33
+
34
+ def removeFile(fullName):
35
+ if os.path.exists(fullName):
36
+ os.remove(fullName)
37
+
38
+
39
+ def is_increasing(lst: list):
40
+ return all(x <= y for x, y in zip(lst, lst[1:]))
41
+
42
+
43
+ class CamDvt(asrCamOp):
44
+ """
45
+ camera Dvt Test
46
+ """
47
+
48
+ def __init__(self, folder=""):
49
+ super(CamDvt, self).__init__()
50
+ self.packageName = "com.asrmicro.camera"
51
+ self.fileAF = "af.log"
52
+ self.fileGainLuma = "gainLuma.log"
53
+ self.fileExpLuma = "expLuma.log"
54
+ self.fileGainBlc = "gainBlc.log"
55
+ self.fileExpBlc = "expBlc.log"
56
+ self.pointAE = 100
57
+ self.pointAF = 100
58
+ self.pointBLC = 8
59
+ self.outPath = self.createOutFolder(folder) if folder else os.path.join(os.getcwd(), "dvtResult")
60
+ self.aeChl = self.checkAeChannel()
61
+
62
+ def checkAeChannel(self):
63
+ cmd = f"{self.tuning_assistant} 127.0.0.1 t 3000 3000 3000 r m0_g0 CAECFilter m_pLumaRLong 5 7"
64
+ try:
65
+ out, _ = pCmd(cmd)
66
+ cmdResult = re.split("[ \n,]+", out)[2]
67
+
68
+ if is_number(cmdResult):
69
+ return 3
70
+ else:
71
+ return 1
72
+ except Exception as e:
73
+ loge(str(e))
74
+ return 1
75
+
76
+ def createOutFolder(self, folderName="result"):
77
+ """
78
+ :以时间戳创建输出目录
79
+ """
80
+
81
+ cmd = f"{self.tuning_assistant} 127.0.0.1 t 3000 3000 3000 gv"
82
+ out, _ = pCmd(cmd)
83
+ if "successfully" in out:
84
+ timestamp = time.strftime("%Y%m%d_%H%M%S", time.localtime())
85
+ outPath = os.path.join(os.getcwd(), folderName + timestamp)
86
+ print("*" * 10, "output is ", outPath)
87
+ os.makedirs(outPath)
88
+ return outPath
89
+ else:
90
+ loge(f"{self.tuning_assistant} 127.0.0.1 t 3000 3000 3000 gv ,error ,please check it !")
91
+ sys.exit()
92
+
93
+ def __blcSetZero(self, maunalEnable: bool):
94
+ self.writeIsp("CDigitalGainFirmwareFilter", "m_bManualMode", 0, 0, maunalEnable)
95
+ for i in range(4):
96
+ self.writeIsp("CDigitalGainFirmwareFilter", "m_pGlobalBlackValueManual", 0, i, 0)
97
+
98
+ def __filterEnable(
99
+ self,
100
+ aeEnable: int,
101
+ afEnable: int,
102
+ awbEnable: int,
103
+ lscEnable: int,
104
+ bpcEnable: int,
105
+ rawDenoiseEnable: int,
106
+ ):
107
+ aeMode = 2 if aeEnable == 1 else 0
108
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, aeMode)
109
+
110
+ self.writeIsp("CWbFirmwareFilter", "m_bEnable", 0, 0, awbEnable)
111
+ self.writeIsp("CAFMFirmwareFilter", "m_bEnable", 0, 0, afEnable)
112
+ self.writeIsp("CLSCFirmwareFilter", "m_bEnable", 0, 0, lscEnable)
113
+ self.writeIsp("CBPCFirmwareFilter", "m_bEnable", 0, 0, bpcEnable)
114
+ self.writeIsp("CRawDenoiseFirmwareFilter", "m_bEnable", 0, 0, rawDenoiseEnable)
115
+
116
+ # debug API
117
+ def manulaGainTest(self):
118
+ step = 8
119
+ gainMin = 1500
120
+ gainMax = 1700
121
+
122
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
123
+ ExpTimeManual = 10000
124
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, ExpTimeManual)
125
+
126
+ self.__filterEnable(1, 0, 0, 0, 0, 0)
127
+ cur = 1
128
+ total = (gainMax - gainMin) // step + 1
129
+ for i in range(gainMin, gainMax + 1, step):
130
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, i)
131
+ time.sleep(0.1)
132
+ luma = self.readIsp("CAECFilter", "m_pLumaMatrixLong", 5, 7, True)
133
+ info = "m_pExpTimeManual(us) = %d m_pTotalGainManual(Q8) = %d luma = %f %d/%d" % (
134
+ ExpTimeManual,
135
+ i,
136
+ luma,
137
+ cur,
138
+ total,
139
+ )
140
+ cur += 1
141
+ logi(info)
142
+ time.sleep(0.1)
143
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
144
+
145
+ # debug API
146
+ def manualExpTest(self):
147
+ step = 100
148
+ expMin = 58550
149
+ expMax = 63050
150
+
151
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
152
+ gainManual = 512
153
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gainManual)
154
+ self.__filterEnable(1, 0, 0, 0, 0, 0)
155
+ cur = 1
156
+ total = (expMax - expMin) // step + 1
157
+ for i in range(expMin, expMax + 1, step):
158
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, i)
159
+ time.sleep(0.1)
160
+ luma = self.readIsp("CAECFilter", "m_pLumaMatrixLong", 5, 7, True)
161
+
162
+ logi(f"m_pExpTimeManual(us) = {i} m_pTotalGainManual(Q8) = {gainManual} luma = {luma} {cur}/{total}")
163
+ cur += 1
164
+ # time.sleep(0.1)
165
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
166
+
167
+ def __getLumaWithGain(self, gain: int):
168
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gain)
169
+ time.sleep(0.6)
170
+ if self.aeChl == 3:
171
+ r = self.readIsp("CAECFilter", "m_pLumaRLong", 5, 7, True)
172
+ g = self.readIsp("CAECFilter", "m_pLumaGLong", 5, 7, True)
173
+ b = self.readIsp("CAECFilter", "m_pLumaBLong", 5, 7, True)
174
+ return [r, g, b]
175
+ elif self.aeChl == 1:
176
+ y = self.readIsp("CAECFilter", "m_pLumaMatrixLong", 5, 7, True)
177
+ return [y]
178
+ else:
179
+ return [0.0, 0.0, 0.0]
180
+
181
+ def __getLumaWithExp(self, exp: int):
182
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, exp)
183
+ time.sleep(0.6)
184
+ if self.aeChl == 3:
185
+ r = self.readIsp("CAECFilter", "m_pLumaRLong", 5, 7, True)
186
+ g = self.readIsp("CAECFilter", "m_pLumaGLong", 5, 7, True)
187
+ b = self.readIsp("CAECFilter", "m_pLumaBLong", 5, 7, True)
188
+ return [r, g, b]
189
+ elif self.aeChl == 1:
190
+ y = self.readIsp("CAECFilter", "m_pLumaMatrixLong", 5, 7, True)
191
+ return [y]
192
+ else:
193
+ return [0.0, 0.0, 0.0]
194
+
195
+ def getVrfMean(self, outPath: str, inVRF: str, fullImg: bool):
196
+ """
197
+ :param raw: raw图->(H, W)
198
+ :return: 12bit meanR,meanGr,meanGb,meanB
199
+ """
200
+
201
+ if not os.path.exists(outPath):
202
+ os.makedirs(outPath)
203
+ self.dumpVrf(outPath, inVRF)
204
+ inVrf = os.path.join(outPath, inVRF)
205
+ outVrf = os.path.join(outPath, os.path.splitext(inVRF)[0] + "_unpack.vrf")
206
+ # asr devices output is packed vrf
207
+ cmd = "imageConvert.exe -i %s -o %s -in_format VRF -out_format VRF" % (
208
+ inVrf,
209
+ outVrf,
210
+ )
211
+ pCmd(cmd)
212
+ removeFile(inVrf)
213
+ vrfObj = asrVrf.Vrf()
214
+ vrfObj.Read(outVrf)
215
+ raw = vrfObj.unpackImage.astype(np.uint16)
216
+ raw = raw.reshape(vrfObj.Height, vrfObj.Width)
217
+
218
+ R = Gr = Gb = B = np.zeros((vrfObj.Height, vrfObj.Width), dtype=np.uint16)
219
+ # 0:BGGR, 1:GBRG, 2:GRBG, 3:RGGB
220
+ if vrfObj.BayerOrder == 3:
221
+ R = raw[0::2, 0::2] # [0,0]
222
+ Gr = raw[0::2, 1::2] # [0,1]
223
+ Gb = raw[1::2, 0::2] # [1,0]
224
+ B = raw[1::2, 1::2] # [1,1]
225
+ elif vrfObj.BayerOrder == 2:
226
+ Gr = raw[0::2, 0::2]
227
+ R = raw[0::2, 1::2]
228
+ B = raw[1::2, 0::2]
229
+ Gb = raw[1::2, 1::2]
230
+ elif vrfObj.BayerOrder == 1:
231
+ Gb = raw[0::2, 0::2]
232
+ B = raw[0::2, 1::2]
233
+ R = raw[1::2, 0::2]
234
+ Gr = raw[1::2, 1::2]
235
+ elif vrfObj.BayerOrder == 0:
236
+ B = raw[0::2, 0::2]
237
+ Gb = raw[0::2, 1::2]
238
+ Gr = raw[1::2, 0::2]
239
+ R = raw[1::2, 1::2]
240
+
241
+ if fullImg:
242
+ meanR = np.mean(R)
243
+ meanGr = np.mean(Gr)
244
+ meanGb = np.mean(Gb)
245
+ meanB = np.mean(B)
246
+ else:
247
+ # 计算中心1/9区域的坐标四个通道的10bit均值
248
+ left = vrfObj.Width // 3
249
+ top = vrfObj.Height // 3
250
+ right = vrfObj.Width - left
251
+ bottom = vrfObj.Height - top
252
+
253
+ # print(left,top,right,bottom)
254
+ meanR = np.mean(R[top:bottom, left:right])
255
+ meanGr = np.mean(Gr[top:bottom, left:right])
256
+ meanGb = np.mean(Gb[top:bottom, left:right])
257
+ meanB = np.mean(B[top:bottom, left:right])
258
+
259
+ needSave = False
260
+ if needSave:
261
+ tmpstr = str(vrfObj.Width // 2) + "x" + str(vrfObj.Height // 2) + ".raw"
262
+ R.tofile(os.path.join(outPath, "ch1_" + tmpstr))
263
+ Gr.tofile(os.path.join(outPath, "ch2_" + tmpstr))
264
+ Gb.tofile(os.path.join(outPath, "ch3_" + tmpstr))
265
+ B.tofile(os.path.join(outPath, "ch4_" + tmpstr))
266
+
267
+ out1 = np.stack((R, Gr), axis=1) # 横向堆叠
268
+ out2 = np.stack((Gb, B), axis=1)
269
+ out = np.stack((out1, out2), axis=0) # 纵向堆叠
270
+ out.tofile(os.path.join(outPath, "out_" + str(vrfObj.Width) + "x" + str(vrfObj.Height) + ".raw"))
271
+
272
+ dgain = vrfObj.TGain / vrfObj.AGain
273
+ # print(meanR,meanGr,meanGb,meanB)
274
+ return (
275
+ round(meanR * dgain * 4, 3),
276
+ round(meanGr * dgain * 4, 3),
277
+ round(meanGb * dgain * 4, 3),
278
+ round(meanB * dgain * 4, 3),
279
+ )
280
+
281
+ def __getGainLumaWithVrf(self, gain: int, exp: int):
282
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gain)
283
+ # self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, exp)
284
+ time.sleep(0.2)
285
+ vrfName = "gain" + str(gain) + "_exp" + str(exp) + ".vrf"
286
+ return self.getVrfMean(self.outPath, vrfName, True)
287
+
288
+ def __getExpLumaWithVrf(self, gain: int, exp: int):
289
+ # self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gain)
290
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, exp)
291
+ time.sleep(0.2)
292
+ vrfName = "gain" + str(gain) + "_exp" + str(exp) + ".vrf"
293
+ return self.getVrfMean(self.outPath, vrfName, True)
294
+
295
+ def __getManual(self, min: int, max: int, flag: str) -> int:
296
+ """手动二分查找目标值"""
297
+ if min == max - 1: # 避免死循环
298
+ return int(min)
299
+
300
+ mid = min + (max - min) // 2
301
+
302
+ if flag == "gain":
303
+ if self.aeChl == 3:
304
+ lumaMin, lumaMid, lumaMax = (
305
+ self.__getLumaWithGain(min)[1],
306
+ self.__getLumaWithGain(mid)[1],
307
+ self.__getLumaWithGain(max)[1],
308
+ )
309
+ else:
310
+ lumaMin, lumaMid, lumaMax = (
311
+ self.__getLumaWithGain(min)[0],
312
+ self.__getLumaWithGain(mid)[0],
313
+ self.__getLumaWithGain(max)[0],
314
+ )
315
+ elif flag == "exp":
316
+ if self.aeChl == 3:
317
+ lumaMin, lumaMid, lumaMax = (
318
+ self.__getLumaWithExp(min)[1],
319
+ self.__getLumaWithExp(mid)[1],
320
+ self.__getLumaWithExp(max)[1],
321
+ )
322
+ else:
323
+ lumaMin, lumaMid, lumaMax = (
324
+ self.__getLumaWithExp(min)[0],
325
+ self.__getLumaWithExp(mid)[0],
326
+ self.__getLumaWithExp(max)[0],
327
+ )
328
+ else:
329
+ return int(min)
330
+
331
+ lumaThr = 220.0 # G channel 过早饱和,导致统计亮度不线性,将门限设低
332
+ if lumaMin is None or lumaMid is None or lumaMax is None:
333
+ exit(f"{flag} manual search error")
334
+
335
+ if lumaMin >= lumaThr:
336
+ return int(min)
337
+ elif lumaMax >= lumaThr:
338
+ if lumaMid >= lumaThr:
339
+ return int(self.__getManual(min, mid, flag))
340
+ return int(self.__getManual(mid, max, flag))
341
+ return int(max)
342
+
343
+ def __getExpTimeManual(self, gainMin, gainMax, expMin, expMax):
344
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
345
+
346
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gainMax)
347
+ print("__getExpTimeManual... gain[%d,%d] exp[%d,%d]" % (gainMin, gainMax, expMin, expMax))
348
+ ExpTimeManual = self.__getManual(expMin, expMax, "exp")
349
+ if expMin == ExpTimeManual:
350
+ print("warning ,environment lux may too high")
351
+ elif expMax == ExpTimeManual:
352
+ print("warning ,environment lux may too low")
353
+
354
+ return int(ExpTimeManual)
355
+
356
+ def __getGainManual(self, gainMin, gainMax, expMin, expMax):
357
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
358
+
359
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, expMax)
360
+ print("__getGainManual... gain[%d,%d] exp[%d,%d]" % (gainMin, gainMax, expMin, expMax))
361
+ # 动态设置增益,使得最大曝光时,统计亮度尽量不饱和
362
+ gainManual = self.__getManual(gainMin, gainMax, "gain")
363
+ if gainMin == gainManual:
364
+ print("warning ,environment lux may too high")
365
+ elif gainMax == gainManual:
366
+ print("warning ,environment lux may too low")
367
+
368
+ return gainManual
369
+
370
+ def __aeGainScanVrf(self, blcTest: bool):
371
+ """
372
+ 遍历AnaGain与VRF亮度
373
+ :blcTest: 测试blc还是亮度
374
+ """
375
+
376
+ # gainMin = self.readIsp("CAECFilter", "m_pMinTotalGain")
377
+ # gainMax = self.readIsp("CAECFilter", "m_pMaxTotalGain")
378
+ gainMin = int(self.readIsp("CAECFilter", "m_pMinAnaGain"))
379
+ gainMax = int(self.readIsp("CAECFilter", "m_pMaxAnaGain"))
380
+ expMin = int(self.readIsp("CAECFilter", "m_pMinExpTime"))
381
+ expMax = int(self.readIsp("CAECFilter", "m_pMaxExpTime"))
382
+ # 动态设置曝光,使得最大增益时,统计亮度尽量不饱和
383
+
384
+ if blcTest:
385
+ logFile = self.fileGainBlc
386
+ ExpTimeManual = expMin
387
+ # ponit = self.pointBLC
388
+ else:
389
+ logFile = self.fileGainLuma
390
+ ExpTimeManual = self.__getExpTimeManual(gainMin, gainMax, expMin, expMax)
391
+ # ponit = self.pointAE
392
+
393
+ # step = (gainMax - gainMin) // ponit
394
+ step = 256
395
+ print("gainMin(Q8)=", gainMin, "gainMax(Q8)=", gainMax, "step=", step)
396
+ print("set ExpTimeManual = ", ExpTimeManual)
397
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, ExpTimeManual)
398
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
399
+
400
+ cur = 1
401
+ total = int(math.log2(math.ceil(gainMax / gainMin))) + 1
402
+ with open(os.path.join(self.outPath, logFile), "a") as f:
403
+ for i in range(0, total):
404
+ gain = int(gainMin * math.pow(2, i))
405
+ meanR, meanGr, meanGb, meanB = self.__getGainLumaWithVrf(gain, ExpTimeManual)
406
+ writeStr = f"m_pExpTimeManual(us) = {ExpTimeManual} m_pTotalGainManual(Q8) = {gain} meanRGGB(12bit) = {meanR} {meanGr} {meanGb} {meanB} {cur}/{total}\n"
407
+ cur += 1
408
+ f.write(writeStr)
409
+ logi(writeStr)
410
+
411
+ time.sleep(1)
412
+
413
+ def __aeExpScanVrf(self, blcTest: bool):
414
+ """
415
+ 遍历ExpTime与VRF亮度
416
+ :blcTest: 测试blc还是亮度
417
+ """
418
+
419
+ # gainMin = self.readIsp("CAECFilter", "m_pMinTotalGain")
420
+ # gainMax = self.readIsp("CAECFilter", "m_pMaxTotalGain")
421
+ gainMin = int(self.readIsp("CAECFilter", "m_pMinAnaGain"))
422
+ gainMax = int(self.readIsp("CAECFilter", "m_pMaxAnaGain"))
423
+ expMin = int(self.readIsp("CAECFilter", "m_pMinExpTime"))
424
+ expMax = int(self.readIsp("CAECFilter", "m_pMaxExpTime"))
425
+
426
+ if blcTest:
427
+ logFile = self.fileExpBlc
428
+ gainManual = gainMin
429
+ ponit = self.pointBLC
430
+ else:
431
+ logFile = self.fileExpLuma
432
+ gainManual = self.__getGainManual(gainMin, gainMax, expMin, expMax)
433
+ ponit = self.pointAE
434
+
435
+ step = (expMax - expMin) // ponit
436
+ print("expMin(us)=", expMin, "expMax(us)=", expMax, "step=", step)
437
+ print("set gainManual = ", gainManual)
438
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gainManual)
439
+ self.writeIsp("CAECFilter", "m_pAnaGainManual", 0, 0, gainManual)
440
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
441
+
442
+ cur = 1
443
+ total = (expMax - expMin) // step + 1
444
+ with open(os.path.join(self.outPath, logFile), "a") as f:
445
+ for i in range(expMin, expMax + 1, step):
446
+ meanR, meanGr, meanGb, meanB = self.__getExpLumaWithVrf(gainManual, i)
447
+ writeStr = f"m_pExpTimeManual(us) = {i} m_pTotalGainManual(Q8) = {gainManual} meanRGGB(12bit) = {meanR} {meanGr} {meanGb} {meanB} {cur}/{total}\n"
448
+ cur += 1
449
+ f.write(writeStr)
450
+ logi(writeStr)
451
+
452
+ time.sleep(1)
453
+
454
+ def __aeGainScanStat(self):
455
+ """
456
+ 遍历totalGain与AEM统计亮度,统计经过BLC,linearization
457
+ """
458
+
459
+ gainMin = int(self.readIsp("CAECFilter", "m_pMinTotalGain"))
460
+ gainMax = int(self.readIsp("CAECFilter", "m_pMaxTotalGain"))
461
+ # gainMin = self.readIsp("CAECFilter", "m_pMinAnaGain")
462
+ # gainMax = self.readIsp("CAECFilter", "m_pMaxAnaGain")
463
+ expMin = self.readIsp("CAECFilter", "m_pMinExpTime")
464
+ expMax = self.readIsp("CAECFilter", "m_pMaxExpTime")
465
+ # 动态设置曝光,使得最大增益时,统计亮度尽量不饱和
466
+ ExpTimeManual = self.__getExpTimeManual(gainMin, gainMax, expMin, expMax)
467
+
468
+ step = (gainMax - gainMin) // self.pointAE
469
+ print("gainMin(Q8)=", gainMin, "gainMax(Q8)=", gainMax, "step=", step)
470
+ print("set ExpTimeManual = ", ExpTimeManual)
471
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
472
+ self.writeIsp("CAECFilter", "m_pExpTimeManual", 0, 0, ExpTimeManual)
473
+
474
+ logFile = self.fileGainLuma
475
+
476
+ cur = 1
477
+ total = (gainMax - gainMin) // step + 1
478
+ writeStr = ''
479
+ with open(os.path.join(self.outPath, logFile), "a") as f:
480
+ for i in range(gainMin, gainMax + 1, step):
481
+ if self.aeChl == 3:
482
+ lumaR, lumaG, lumaB = self.__getLumaWithGain(i)
483
+ writeStr = (
484
+ "m_pExpTimeManual(us) = %d m_pTotalGainManual(Q8) = %d lumaRGB(8bit) = %f %f %f %d/%d\n"
485
+ % (ExpTimeManual, i, lumaR, lumaG, lumaB, cur, total)
486
+ )
487
+ elif self.aeChl == 1:
488
+ luma = self.__getLumaWithGain(i)
489
+ writeStr = "m_pExpTimeManual(us) = %d m_pTotalGainManual(Q8) = %d luma(8bit) = %f %d/%d\n" % (
490
+ ExpTimeManual,
491
+ i,
492
+ luma,
493
+ cur,
494
+ total,
495
+ )
496
+ cur += 1
497
+ f.write(writeStr)
498
+ logi(writeStr.replace("\n", "").replace("\r", ""))
499
+
500
+ time.sleep(1)
501
+
502
+ def __aeExpScanStat(self):
503
+ """
504
+ 遍历ExpTime与AEM统计亮度,统计经过BLC,linearization
505
+ """
506
+
507
+ gainMin = int(self.readIsp("CAECFilter", "m_pMinTotalGain"))
508
+ gainMax = int(self.readIsp("CAECFilter", "m_pMaxTotalGain"))
509
+ # gainMin = self.readIsp("CAECFilter", "m_pMinAnaGain")
510
+ # gainMax = self.readIsp("CAECFilter", "m_pMaxAnaGain")
511
+ expMin = int(self.readIsp("CAECFilter", "m_pMinExpTime"))
512
+ expMax = int(self.readIsp("CAECFilter", "m_pMaxExpTime"))
513
+ # 动态设置曝光,使得最大增益时,统计亮度尽量不饱和
514
+ gainManual = self.__getGainManual(gainMin, gainMax, expMin, expMax)
515
+
516
+ step = (expMax - expMin) // self.pointAE
517
+ print("expMin(us)=", expMin, "expMax(us)=", expMax, "step=", step)
518
+ print("set gainManual = ", gainManual)
519
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
520
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gainManual)
521
+
522
+ logFile = self.fileExpLuma
523
+ cur = 1
524
+ total = (expMax - expMin) // step + 1
525
+ writeStr = ''
526
+ with open(os.path.join(self.outPath, logFile), "a") as f:
527
+ for i in range(expMin, expMax + 1, step):
528
+ if self.aeChl == 3:
529
+ lumaR, lumaG, lumaB = self.__getLumaWithExp(i)
530
+ writeStr = (
531
+ "m_pExpTimeManual(us) = %d m_pTotalGainManual(Q8) = %d lumaRGB(8bit) = %f %f %f %d/%d\n"
532
+ % (i, gainManual, lumaR, lumaG, lumaB, cur, total)
533
+ )
534
+
535
+ elif self.aeChl == 1:
536
+ luma = self.__getLumaWithExp(i)
537
+ writeStr = "m_pExpTimeManual(us) = %d m_pTotalGainManual(Q8) = %d luma(8bit) = %f %d/%d\n" % (
538
+ i,
539
+ gainManual,
540
+ luma,
541
+ cur,
542
+ total,
543
+ )
544
+ cur += 1
545
+ f.write(writeStr)
546
+ logi(writeStr.replace("\n", "").replace("\r", ""))
547
+
548
+ time.sleep(1)
549
+
550
+ def calibrateAE(self):
551
+ m_pExpIndexLong = self.readIsp("CAECFilter", "m_pExpIndexLong", 0, 0, False)
552
+ m_nLumaQ16 = self.readIsp("CAECFilter", "m_nLumaQ16", 0, 0, False)
553
+ logi(f"m_pExpIndexLong={m_pExpIndexLong}, m_nLumaQ16={m_nLumaQ16}")
554
+
555
+ self.writeIsp("CAECFilter", "m_nCalibExposureIndex", 0, 0, m_pExpIndexLong)
556
+ self.writeIsp("CAECFilter", "m_nCalibSceneLuma", 0, 0, m_nLumaQ16)
557
+
558
+ m_nCurLux = int(input(f"请输入当前照度lux: "))
559
+ self.writeIsp("CAECFilter", "m_nCalibSceneLux", 0, 0, m_nCurLux)
560
+
561
+ @staticmethod
562
+ def plotCurve(
563
+ out_path: str,
564
+ txt_file: str,
565
+ title: str,
566
+ xlabel: str,
567
+ ylabel: str,
568
+ col_x: int,
569
+ col_y: int,
570
+ fig=None,
571
+ ):
572
+ """
573
+ :param out_path: 需要读取的测试结果文件路径
574
+ :param txt_file: 需要读取的测试结果文件
575
+ :param title: 图表标题
576
+ :param xlabel: 图表x轴名称
577
+ :param ylabel: 图表y轴名称
578
+ :param col_x: 图表x轴数据所在列
579
+ :param col_y: 图表y轴数据所在列
580
+ :param fig: figure类,用于重绘曲线
581
+ """
582
+ needSave = 0
583
+
584
+ x = []
585
+ y = []
586
+ with open(os.path.join(out_path, txt_file), "r") as fp:
587
+ line = fp.readline()
588
+
589
+ while line:
590
+ # print(line.strip().split(' '))
591
+ x.append(float(line.strip().split(" ")[col_x])) # get column col_x as x
592
+ y.append(float(line.strip().split(" ")[col_y])) # get column col_y as y
593
+ line = fp.readline()
594
+
595
+ # if not is_increasing(x) or not is_increasing(y):
596
+ # loge("%s not increasing, please check the %s " % (ylabel, title))
597
+
598
+ # print(x,y)
599
+ if fig == None:
600
+ fig = plt.figure(figsize=(16, 9))
601
+ needSave = 1
602
+ a1 = fig.add_axes((0.12, 0.1, 0.85, 0.85))
603
+ a1.plot(x, y, "r", linewidth=0.3)
604
+ a1.set_title(title)
605
+ # 设置y轴
606
+ a1.set_ylabel(ylabel)
607
+ # 设置x轴
608
+ a1.set_xlabel(xlabel)
609
+ # 设置grid
610
+ a1.grid(color="b", ls="-.", linewidth=0.3)
611
+ # 设置x从0开始
612
+ a1.set_xlim(0, max(x))
613
+
614
+ # 设置坐标轴刻度
615
+ ticks_x = np.linspace(0, max(x) + x[1] - x[0], 8)
616
+ ticks_y = np.linspace(0, max(y) + 10, 8)
617
+ a1.set_xticks(ticks_x)
618
+ a1.set_yticks(ticks_y)
619
+ if needSave == 1:
620
+ plt.savefig(os.path.join(out_path, title + ".png"))
621
+ plt.show()
622
+
623
+ @staticmethod
624
+ def plot3Curve(
625
+ out_path: str,
626
+ txt_file: str,
627
+ title: str,
628
+ xlabel: str,
629
+ ylabel: str,
630
+ col_x: int,
631
+ col_y: int,
632
+ fig=None,
633
+ ):
634
+ """
635
+ :param out_path: 需要读取的测试结果文件路径
636
+ :param txt_file: 需要读取的测试结果文件
637
+ :param title: 图表标题
638
+ :param xlabel: 图表x轴名称
639
+ :param ylabel: 图表y轴名称
640
+ :param col_x: 图表x轴数据所在列
641
+ :param col_y: 图表y轴数据所在列
642
+ :param fig: figure类,用于重绘曲线
643
+ """
644
+ needSave = 0
645
+
646
+ x = []
647
+ r = []
648
+ g = []
649
+ b = []
650
+ with open(os.path.join(out_path, txt_file), "r") as fp:
651
+ line = fp.readline()
652
+
653
+ while line:
654
+ # print(line.strip().split(' '))
655
+ x.append(float(line.strip().split(" ")[col_x])) # get column col_x as x
656
+ r.append(float(line.strip().split(" ")[col_y])) # get column col_y as r
657
+ g.append(float(line.strip().split(" ")[col_y + 1]))
658
+ b.append(float(line.strip().split(" ")[col_y + 2]))
659
+ line = fp.readline()
660
+
661
+ if not is_increasing(x) or not is_increasing(r) or not is_increasing(g) or not is_increasing(b):
662
+ loge("%s not increasing, please check the %s " % (ylabel, title))
663
+
664
+ # print(x,y)
665
+ if fig == None:
666
+ fig = plt.figure(figsize=(16, 9))
667
+ needSave = 1
668
+ a1 = fig.add_axes((0.12, 0.1, 0.85, 0.85))
669
+ a1.plot(
670
+ x,
671
+ r,
672
+ color="red",
673
+ label="R",
674
+ linewidth=0.3,
675
+ )
676
+ a1.plot(x, g, color="green", label="G", linewidth=0.3)
677
+ a1.plot(x, b, color="blue", label="B", linewidth=0.3)
678
+ a1.set_title(title)
679
+ # 设置y轴
680
+ a1.set_ylabel(ylabel)
681
+ # 设置x轴
682
+ a1.set_xlabel(xlabel)
683
+ # 设置grid
684
+ a1.grid(color="Magenta", ls="-.", lw=0.35)
685
+ # 设置x从0开始
686
+ a1.set_xlim(0, max(x))
687
+ a1.legend()
688
+ # 设置坐标轴刻度
689
+ ticks_x = np.linspace(0, max(x) + x[1] - x[0], 8)
690
+ ticks_y = np.linspace(0, max(max(r), max(g), max(b)) + 10, 8)
691
+ a1.set_xticks(ticks_x)
692
+ a1.set_yticks(ticks_y)
693
+ if needSave == 1:
694
+ plt.savefig(os.path.join(out_path, title + ".png"))
695
+ # plt.show()
696
+
697
+ @staticmethod
698
+ def plot4Curve(
699
+ out_path: str,
700
+ txt_file: str,
701
+ title: str,
702
+ xlabel: str,
703
+ ylabel: str,
704
+ col_x: int,
705
+ col_y: int,
706
+ fig=None,
707
+ ):
708
+ """
709
+ :param out_path: 需要读取的测试结果文件路径
710
+ :param txt_file: 需要读取的测试结果文件
711
+ :param title: 图表标题
712
+ :param xlabel: 图表x轴名称
713
+ :param ylabel: 图表y轴名称
714
+ :param col_x: 图表x轴数据所在列
715
+ :param col_y: 图表y轴数据所在列
716
+ :param fig: figure类,用于重绘曲线
717
+ """
718
+ needSave = 0
719
+
720
+ x = []
721
+ r = []
722
+ gr = []
723
+ gb = []
724
+ b = []
725
+ with open(os.path.join(out_path, txt_file), "r") as fp:
726
+ line = fp.readline()
727
+
728
+ while line:
729
+ # print(line.strip().split(' '))
730
+ # rc = re.compile(r"(m_pExpTimeManual.*?|m_pTotalGainManual.*?|meanRGGB.*?) = (\d+|\d+\.\d+)")
731
+ # print(rc.findall(line))
732
+ x.append(float(line.strip().split()[col_x])) # get column col_x as x
733
+ r.append(float(line.strip().split()[col_y])) # get column col_y as r
734
+ gr.append(float(line.strip().split()[col_y + 1]))
735
+ gb.append(float(line.strip().split()[col_y + 2]))
736
+ b.append(float(line.strip().split()[col_y + 3]))
737
+ line = fp.readline()
738
+
739
+ if fig == None:
740
+ fig = plt.figure(figsize=(16, 9))
741
+ needSave = 1
742
+ a1 = fig.add_axes((0.12, 0.1, 0.85, 0.85))
743
+
744
+ a1.plot(x, r, color="red", label="R", linewidth=0.3)
745
+ a1.plot(x, gr, color=("yellowgreen"), label="Gr", linewidth=0.3)
746
+ a1.plot(x, gb, color="lightgreen", label="Gb", linewidth=0.3)
747
+ a1.plot(x, b, color="blue", label="B", linewidth=0.3)
748
+ a1.set_title(title)
749
+ # 设置y轴
750
+ a1.set_ylabel(ylabel)
751
+ # 设置x轴
752
+ a1.set_xlabel(xlabel)
753
+ # 设置grid
754
+ a1.grid(color="Magenta", ls="-.", lw=0.35)
755
+ # 设置x从0开始
756
+ a1.set_xlim(0, max(x))
757
+ a1.legend()
758
+ # 设置坐标轴刻度
759
+ ticks_x = np.linspace(0, max(x) + x[1] - x[0], 8)
760
+ ticks_y = np.linspace(0, max(max(r), max(gr), max(gb), max(b)) + 10, 8)
761
+ a1.set_xticks(ticks_x)
762
+ a1.set_yticks(ticks_y)
763
+ if needSave == 1:
764
+ plt.savefig(os.path.join(out_path, title + ".png"))
765
+ # plt.show()
766
+
767
+ def aeVrfDvt(self):
768
+ """
769
+ 1. 光源需直流无频闪,照度约 800-1000lux
770
+ """
771
+
772
+ self.__filterEnable(1, 0, 0, 0, 0, 0)
773
+
774
+ self.__aeGainScanVrf(False)
775
+ self.plot4Curve(
776
+ self.outPath,
777
+ self.fileGainLuma,
778
+ "Gain-Luma",
779
+ "Gain(Q8)",
780
+ "Luma(10bit)",
781
+ 5,
782
+ 8,
783
+ )
784
+
785
+ self.__aeExpScanVrf(False)
786
+ self.plot4Curve(self.outPath, self.fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(10bit)", 2, 8)
787
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
788
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 0)
789
+
790
+ def aeStatDvt(self):
791
+ """
792
+ 1. 光源需直流无频闪,照度约 800-1000lux
793
+ """
794
+
795
+ self.__filterEnable(1, 0, 0, 0, 0, 0)
796
+
797
+ self.__aeGainScanStat()
798
+ if self.aeChl == 3:
799
+ self.plot3Curve(
800
+ self.outPath,
801
+ self.fileGainLuma,
802
+ "Gain-Luma",
803
+ "Gain(Q8)",
804
+ "Luma(8bit)",
805
+ 5,
806
+ 8,
807
+ )
808
+ elif self.aeChl == 1:
809
+ self.plotCurve(
810
+ self.outPath,
811
+ self.fileGainLuma,
812
+ "Gain-Luma",
813
+ "Gain(Q8)",
814
+ "Luma(8bit)",
815
+ 5,
816
+ 8,
817
+ )
818
+ self.__aeExpScanStat()
819
+ if self.aeChl == 3:
820
+ self.plot3Curve(self.outPath, self.fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(8bit)", 2, 8)
821
+ elif self.aeChl == 1:
822
+ self.plotCurve(self.outPath, self.fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(8bit)", 2, 8)
823
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
824
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 0)
825
+
826
+ def blcDvt(self):
827
+ """
828
+ 1. 全黑环境
829
+ """
830
+
831
+ self.__filterEnable(1, 0, 0, 0, 0, 0)
832
+ self.__aeGainScanVrf(True)
833
+ self.plot4Curve(self.outPath, self.fileGainBlc, "Gain-blc", "Gain(Q8)", "blc(10bit)", 5, 8)
834
+
835
+ self.__aeExpScanVrf(True)
836
+ self.plot4Curve(self.outPath, self.fileExpBlc, "Exp-blc", "Exp(us)", "blc(10bit)", 2, 8)
837
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
838
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 0)
839
+
840
+ def blcScanVrf(self):
841
+ """
842
+ 遍历AnaGain与VRF
843
+ """
844
+ # gainMin = self.readIsp("CAECFilter", "m_pMinAnaGain")
845
+ gainMin = 256
846
+ gainMax = self.readIsp("CAECFilter", "m_pMaxAnaGain")
847
+ print("gainMin(Q8)=", gainMin, "gainMax(Q8)=", gainMax)
848
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 1)
849
+ pCmd("adb shell rm data/vendor/camera/*", 1)
850
+ pCmd("adb shell setprop persist.vendor.camera.enable.capturedump 1", 0.5)
851
+ # outPath = os.path.join(self.outPath, "raw")
852
+ outPath = self.outPath
853
+ if not os.path.exists(outPath):
854
+ os.makedirs(outPath)
855
+ for i in range(0, int(math.log2(math.ceil(gainMax / gainMin))) + 1):
856
+ gain = int(gainMin * math.pow(2, i))
857
+ print("gain(Q8)=", gain)
858
+ self.writeIsp("CAECFilter", "m_pTotalGainManual", 0, 0, gain)
859
+ self.writeIsp("CAECFilter", "m_pAnaGainManual", 0, 0, gain)
860
+ time.sleep(0.2)
861
+ vrfName = "gain_" + str(gain // 256) + ".vrf"
862
+ self.dumpVrf(outPath, vrfName)
863
+ # pCmd("adb shell input keyevent 27",sleep_s=5)
864
+
865
+ time.sleep(1)
866
+
867
+ def gainScanVrf(self):
868
+ """
869
+ 遍历AnaGain与VRF
870
+ """
871
+
872
+ gainMin = 256
873
+ gainMax = self.readIsp("CAECFilter", "m_pMaxAnaGain")
874
+ print("gainMin(Q8)=", gainMin, "gainMax(Q8)=", gainMax)
875
+ self.writeIsp("CAECFilter", "m_bManualAEEnable", 0, 0, 0)
876
+ pCmd("adb shell rm data/vendor/camera/*", 1)
877
+ pCmd("adb shell setprop persist.vendor.camera.enable.capturedump 1", 0.5)
878
+ # outPath = os.path.join(self.outPath, "raw")
879
+ outPath = self.outPath
880
+ if not os.path.exists(outPath):
881
+ os.makedirs(outPath)
882
+ for i in range(0, int(math.log2(math.ceil(gainMax / gainMin))) + 1):
883
+ gain = int(gainMin * math.pow(2, i))
884
+ print("gain(Q8)=", gain)
885
+ self.writeIsp("CAECFilter", "m_pMinAnaGain", 0, 0, gain)
886
+ self.writeIsp("CAECFilter", "m_pMaxAnaGain", 0, 0, gain)
887
+ self.writeIsp("CAECFilter", "m_pMinTotalGain", 0, 0, gain)
888
+ self.writeIsp("CAECFilter", "m_pMaxTotalGain", 0, 0, gain)
889
+ time.sleep(0.2)
890
+ vrfName = "gain_" + str(gain // 256) + ".vrf"
891
+ self.dumpVrf(outPath, vrfName)
892
+ # pCmd("adb shell input keyevent 27",sleep_s=5)
893
+
894
+ time.sleep(1)
895
+
896
+ def afScan(self):
897
+ """
898
+ 遍历AF position与FV
899
+ """
900
+
901
+ # full scan
902
+ startPosition = 0
903
+ endPosition = 1023
904
+ step = (endPosition - startPosition) // self.pointAF
905
+
906
+ self.writeIsp("CAFFilter", "m_nMinMotorPosition", 0, 0, startPosition)
907
+ self.writeIsp("CAFFilter", "m_nMaxMotorPosition", 0, 0, endPosition)
908
+ logi(f"startPosition= {startPosition}, endPosition= {endPosition}, step= {step}")
909
+
910
+ self.writeIsp("CAFFilter", "m_bAFTrigger", 0, 0, 0)
911
+
912
+ cur = 1
913
+ total = (endPosition - startPosition) // step + 1
914
+ with open(os.path.join(self.outPath, self.fileAF), "a") as f:
915
+ for i in range(startPosition, endPosition + 1, step):
916
+ self.writeIsp("CAFFilter", "m_nManualMotorPosition", 0, 0, i)
917
+ self.writeIsp("CAFFilter", "m_bMotorManualTrigger", 0, 0, 1)
918
+ time.sleep(1)
919
+ m_pRTFVList = self.readIsp("CAFFilter", "m_pRTFVList", 0, 0, False)
920
+
921
+ writeStr = "%d/%d position = %d FV = %d \n" % (cur, total, i, m_pRTFVList)
922
+ cur += 1
923
+ f.write(writeStr)
924
+ logi(writeStr.replace("\n", "").replace("\r", ""))
925
+
926
+ time.sleep(1)
927
+
928
+ def dumpPDVrf(self, outPath: str, posCode: str):
929
+ cmd = f"{self.tuning_assistant} 127.0.0.1 t 3000 3000 3000 dp m0_g0 {outPath} 1"
930
+ out = pCmd(cmd)
931
+
932
+ # 使用正则表达式查找关键词之间的字符串
933
+ keyword1 = "ID="
934
+ keyword2 = "\n"
935
+ match = re.search(f"{keyword1}(.*?){keyword2}", out[0])
936
+ if match:
937
+ ch0 = str(match.group(1)) + "_0.vrf"
938
+ ch1 = str(match.group(1)) + "_1.vrf"
939
+ fullpath0 = os.path.join(outPath, ch0)
940
+ fullpath1 = os.path.join(outPath, ch1)
941
+ newfile0 = os.path.join(outPath, str(posCode) + "_L.vrf")
942
+ newfile1 = os.path.join(outPath, str(posCode) + "_R.vrf")
943
+ renameFile(newfile0, fullpath0)
944
+ renameFile(newfile1, fullpath1)
945
+ else:
946
+ print("抓取vrf失败")
947
+ sys.exit()
948
+
949
+ def pdafScan(self, isType2=False):
950
+ """
951
+ 抓取11张不同position的vrf
952
+ """
953
+
954
+ # full scan
955
+ startPosition = int(self.readIsp("CAFFilter", "m_nMinMotorPosition", 0, 0, False))
956
+ endPosition = int(self.readIsp("CAFFilter", "m_nMaxMotorPosition", 0, 0, False))
957
+ step = (endPosition - startPosition) // 10
958
+
959
+ logi(f"startPosition= {startPosition}, endPosition= {endPosition}, step= {step}")
960
+
961
+ self.writeIsp("CAFFilter", "m_bAFTrigger", 0, 0, 0)
962
+
963
+ if isType2:
964
+ self.writeIsp("CPDC64FirmwareFilter", "m_nWindowMode", 0, 0, 2)
965
+
966
+ cur = 1
967
+ total = (endPosition - startPosition) // step + 1
968
+ for i in range(startPosition, endPosition + 1, step):
969
+ self.writeIsp("CAFFilter", "m_nManualMotorPosition", 0, 0, i)
970
+ self.writeIsp("CAFFilter", "m_bMotorManualTrigger", 0, 0, 1)
971
+ time.sleep(2)
972
+ # outPath = os.path.join(self.outPath, "raw")
973
+ outPath = self.outPath
974
+ if not os.path.exists(outPath):
975
+ os.makedirs(outPath)
976
+ if isType2:
977
+ self.dumpPDVrf(outPath, str(i))
978
+ self.dumpVrf(outPath, str(i) + ".vrf")
979
+ else:
980
+ self.dumpVrf(outPath, str(i) + ".vrf")
981
+ logi(f"position = {i} {cur}/{total}")
982
+ cur += 1
983
+ time.sleep(1)
984
+
985
+ def afDvt(self):
986
+ """
987
+ 光源需直流无频闪,照度800lux, 50cm距离细节丰富的chart
988
+ """
989
+
990
+ pCmd("adb shell input keyevent KEYCODE_HOME", 3)
991
+ pCmd("adb shell am start -a android.media.action.STILL_IMAGE_CAMERA", 2)
992
+
993
+ self.__filterEnable(0, 1, 0, 0, 0, 0)
994
+
995
+ self.afScan()
996
+ self.plotCurve(self.outPath, self.fileAF, "position-FV", "position", "FV", 3, 6)
997
+
998
+ self.__filterEnable(1, 1, 1, 1, 1, 1)
999
+
1000
+
1001
+ def reDrawAE(outPath: str, chl: int):
1002
+ """
1003
+ 再次绘制AE曲线
1004
+ :outPath: log文件夹
1005
+ :chl 曲线是三通道还是四通道
1006
+ """
1007
+
1008
+ fileGainLuma = "gainLuma.log"
1009
+ fileExpLuma = "expLuma.log"
1010
+ plt.ion() # 开启interactive mode
1011
+ fig1 = plt.figure(1, figsize=(16, 9))
1012
+ fig2 = plt.figure(2, figsize=(16, 9))
1013
+ if chl == 4:
1014
+ CamDvt.plot4Curve(outPath, fileGainLuma, "Gain-Luma", "Gain(Q8)", "Luma(10bit)", 5, 8, fig1)
1015
+ CamDvt.plot4Curve(outPath, fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(10bit)", 2, 8, fig2)
1016
+ elif chl == 3:
1017
+ CamDvt.plot3Curve(outPath, fileGainLuma, "Gain-Luma", "Gain(Q8)", "Luma(8bit)", 5, 8, fig1)
1018
+ CamDvt.plot3Curve(outPath, fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(8bit)", 2, 8, fig2)
1019
+ elif chl == 1:
1020
+ CamDvt.plotCurve(outPath, fileGainLuma, "Gain-Luma", "Gain(Q8)", "Luma(8bit)", 5, 8, fig1)
1021
+ CamDvt.plotCurve(outPath, fileExpLuma, "Exp-Luma", "Exp(us)", "Luma(8bit)", 2, 8, fig2)
1022
+ plt.ioff() # 关闭interactive mode
1023
+ plt.show() # 显示图像1,2并且阻塞程序
1024
+
1025
+
1026
+ def reDrawBLC(outPath: str):
1027
+ fileGainBlc = "gainBlc.log"
1028
+ fileExpBlc = "expBlc.log"
1029
+ plt.ion() # 开启interactive mode
1030
+ fig1 = plt.figure(1, figsize=(16, 9))
1031
+ fig2 = plt.figure(2, figsize=(16, 9))
1032
+ CamDvt.plot4Curve(outPath, fileGainBlc, "Gain-blc", "Gain(Q8)", "blc(10bit)", 5, 8, fig1)
1033
+ CamDvt.plot4Curve(outPath, fileExpBlc, "Exp-blc", "Exp(us)", "blc(10bit)", 2, 8, fig2)
1034
+ plt.ioff() # 关闭interactive mode
1035
+ plt.show() # 显示图像1,2并且阻塞程序
1036
+
1037
+
1038
+ def reDrawAF(outPath: str):
1039
+ fileAF = "af.log"
1040
+ plt.ion()
1041
+ fig1 = plt.figure(1, figsize=(16, 9))
1042
+ CamDvt.plotCurve(outPath, fileAF, "position-FV", "position", "FV", 3, 6, fig1)
1043
+ plt.ioff()
1044
+ plt.show()
1045
+
1046
+
1047
+ def CLI_aeDVT(argsList):
1048
+ parser = argparse.ArgumentParser(
1049
+ prog="aeDvt", description="测试AE线性度" "光源需直流无频闪,照度800lux, 镜头前使用diffuse盖住"
1050
+ )
1051
+ parser.add_argument(
1052
+ "-t", "--type", type=str, required=True, default="statistic", choices=["vrf", "statistic"], help="统计方式"
1053
+ )
1054
+ args = parser.parse_args(argsList)
1055
+
1056
+ start_time = time.time()
1057
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1058
+ if args.type == "vrf":
1059
+ dvt.aeVrfDvt()
1060
+ else:
1061
+ dvt.aeStatDvt()
1062
+ end_time = time.time()
1063
+ elapsed_time = int(end_time - start_time)
1064
+ print(f"测试耗时:{elapsed_time} 秒")
1065
+
1066
+
1067
+ def CLI_afDVT():
1068
+ """
1069
+ 光源需直流无频闪,照度800lux, 50cm距离细节丰富的chart
1070
+ """
1071
+
1072
+ start_time = time.time()
1073
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1074
+ dvt.afDvt()
1075
+ end_time = time.time()
1076
+ elapsed_time = int(end_time - start_time)
1077
+ print(f"测试耗时:{elapsed_time} 秒")
1078
+
1079
+
1080
+ def CLI_pdafCap(argsList):
1081
+ parser = argparse.ArgumentParser(
1082
+ prog="pdafVrfCap",
1083
+ description="抓取不同position的vrf,用于pdaf测试"
1084
+ "光源需直流无频闪,照度800lux, 据棋盘格距离为 对焦范围中间位合焦位置",
1085
+ )
1086
+ parser.add_argument(
1087
+ "-t", "--type", type=str, required=True, default="type2", choices=["type2", "type3"], help="pdaf类型"
1088
+ )
1089
+ args = parser.parse_args(argsList)
1090
+
1091
+ isType2 = False
1092
+ if args.type == "type2":
1093
+ isType2 = True
1094
+ logi("pdaf type2")
1095
+ else:
1096
+ logi("pdaf type3")
1097
+ start_time = time.time()
1098
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1099
+ dvt.pdafScan(isType2)
1100
+ end_time = time.time()
1101
+ elapsed_time = int(end_time - start_time)
1102
+ print(f"测试耗时:{elapsed_time} 秒")
1103
+
1104
+
1105
+ def CLI_gainScan():
1106
+ start_time = time.time()
1107
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1108
+ dvt.gainScanVrf()
1109
+ end_time = time.time()
1110
+ elapsed_time = int(end_time - start_time)
1111
+ print(f"测试耗时:{elapsed_time} 秒")
1112
+
1113
+
1114
+ def CLI_blcScan():
1115
+ """
1116
+ 1. 全黑环境
1117
+ """
1118
+
1119
+ start_time = time.time()
1120
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1121
+ dvt.blcScanVrf()
1122
+ end_time = time.time()
1123
+ elapsed_time = int(end_time - start_time)
1124
+ print(f"测试耗时:{elapsed_time} 秒")
1125
+
1126
+
1127
+ def CLI_blcDVT():
1128
+ """
1129
+ 1. 全黑环境
1130
+ """
1131
+
1132
+ start_time = time.time()
1133
+ dvt = CamDvt(sys._getframe(0).f_code.co_name)
1134
+ dvt.blcDvt()
1135
+ end_time = time.time()
1136
+ elapsed_time = int(end_time - start_time)
1137
+ print(f"测试耗时:{elapsed_time} 秒")
1138
+
1139
+
1140
+ def CLI_calibAE():
1141
+ dvt = CamDvt()
1142
+ dvt.calibrateAE()
1143
+
1144
+
1145
+ _COMMAND_REGISTRY = {}
1146
+
1147
+
1148
+ def printHelp():
1149
+ print("[camDvt]")
1150
+ print("ae -h :ae dvt with vrf/statistic [800lux, no flicker with diffuse]")
1151
+ print("af :af dvt [光源需直流无频闪,照度800lux, 50cm距离细节丰富的chart]")
1152
+ print("pdaf -h :pdaf capture 31 frames [直流无频闪,照度800lux, 据棋盘格距离为 对焦范围中间位合焦位置]")
1153
+ print("blc :blc dvt [全黑环境]")
1154
+ print("blcscan :blc scan [全黑环境]")
1155
+ print("gainscan :gain scan [gain 指数增加]")
1156
+ print("calae :AE校准")
1157
+
1158
+
1159
+ CLI_aeDVT = register_command("ae", registry=_COMMAND_REGISTRY)(CLI_aeDVT)
1160
+ CLI_afDVT = register_command("af", registry=_COMMAND_REGISTRY)(CLI_afDVT)
1161
+ CLI_blcDVT = register_command("blc", registry=_COMMAND_REGISTRY)(CLI_blcDVT)
1162
+ CLI_pdafCap = register_command("pdaf", registry=_COMMAND_REGISTRY)(CLI_pdafCap)
1163
+ CLI_blcScan = register_command("blcscan", registry=_COMMAND_REGISTRY)(CLI_blcScan)
1164
+ CLI_gainScan = register_command("gainscan", registry=_COMMAND_REGISTRY)(CLI_gainScan)
1165
+ CLI_calibAE = register_command("calae", registry=_COMMAND_REGISTRY)(CLI_calibAE)
1166
+
1167
+
1168
+ def camDvtMain(args):
1169
+ debugCtrl(1) if "debug" in args else debugCtrl(0)
1170
+ args.remove("debug") if "debug" in args else args
1171
+ args = normalize_args(args)
1172
+ if len(args) < 1 or args[0] in {"help", "-h", "--help"}:
1173
+ printHelp()
1174
+ return
1175
+ cmd = args[0]
1176
+ handler = _COMMAND_REGISTRY.get(cmd)
1177
+ if handler is None:
1178
+ loge(f"unsupport command {cmd}")
1179
+ return
1180
+ handler(args[1:])
1181
+
1182
+
1183
+ if __name__ == "__main__":
1184
+ debugCtrl(1) if "debug" in sys.argv else debugCtrl(0)
1185
+ sys.argv.remove("debug") if "debug" in sys.argv else sys.argv
1186
+ camDvtMain(sys.argv)