Open vieyahn2017 opened 1 year ago
pip install traceback-with-variables
yh_cv2_log.py
import sys
import cvlog
import numpy as np
# from traceback_with_variables import activate_by_import
cvlog.set_mode(cvlog.Mode.LOG) # log_image
# cvlog.set_mode(cvlog.Mode.DEBUG) # show_image
cvlog.set_level(cvlog.Level.TRACE)
# test
def get_vars(frame_no=1):
frame = sys._getframe(frame_no)
print(frame.f_globals.items())
print(frame.f_locals.items())
# 初步完成我的需求
# todo:动态变量监控,比如img一直在被重新赋值,动态记录
# todo:pyQt5做界面那种,Halcaon那种
def check_image_and_log(frame_no=1, mark_image=None, lineno=0):
def _check_is_image(items, _shape=None):
""" _shape传None的时候,取第一个符合要求的 """
if _shape is None:
for k, v in items:
if type(v) == np.ndarray:
if len(v.shape) == 3 and v.shape[2] == 3:
check_shape = v.shape
else:
check_shape = _shape
try:
_rows, _cols = check_shape[:2]
except:
print("shape is invalid, maybe image is not existed.")
return
for k, v in items:
# print(k)
# print(type(v))
if type(v) == np.ndarray:
if len(v.shape) not in [2, 3]:
continue
if len(v.shape) == 3 and v.shape[2] != 3:
continue
# 对 _rows, _cols的匹配,目前看貌似没必要
print("Line[{}]: {} is matched, shape is {}".format(lineno, k, v.shape))
cvlog.image(cvlog.Level.INFO, v, msg="{} at {}".format(k, lineno))
shape = None
if mark_image is not None:
shape = mark_image.shape
frame = sys._getframe(frame_no)
func = frame.f_code.co_name
lineno = frame.f_lineno
# print(frame.f_globals.keys())
print(list(filter(lambda x: not x.startswith("__"), frame.f_globals.keys())))
_check_is_image(frame.f_globals.items(), shape)
if func != "<module>":
# print(frame.f_locals.items())
print(list(filter(lambda x: not x.startswith("__"), frame.f_locals.keys())))
_check_is_image(frame.f_locals.items(), shape)
最新:
import sys
import cvlog
import numpy as np
# from traceback_with_variables import activate_by_import
cvlog.set_mode(cvlog.Mode.LOG) # log_image
# cvlog.set_mode(cvlog.Mode.DEBUG) # show_image
cvlog.set_level(cvlog.Level.TRACE)
GLOBAL_HASH_DICT = dict()
# 1. 初步完成我的需求
# 2. images限定。已完成。测试语句 check_image_and_log(images=["image", "mask", "not_existed"])
# 3. 全局变量在当前函数没有改变,不做记录 【新加入GLOBAL_HASH_DICT,基本实现】
# todo:动态变量监控,比如img一直在被重新赋值,动态记录 【暂时没思路】(使用上规避了,单个上下文内,不要做变量覆盖写)
# 5. 优化cvlog的结果显示html_template 【基本完成】
# todo:pyQt5做界面那种,Halcaon那种
def check_image_and_log(frame_no=1, base_image=None, images=[]):
frame = sys._getframe(frame_no)
func = frame.f_code.co_name
lineno = frame.f_lineno
print(("GLOBAL_HASH_DICT:"), GLOBAL_HASH_DICT.items())
if len(images) > 1:
frame = sys._getframe(frame_no)
func = frame.f_code.co_name
lineno = frame.f_lineno
f_globals = list(filter(lambda x: not x.startswith("__"), frame.f_globals.keys()))
f_locals = list(filter(lambda x: not x.startswith("__"), frame.f_locals.keys()))
for imgk in images:
if imgk in f_locals:
v = frame.f_locals[imgk]
cvlog.image(cvlog.Level.INFO, v, msg="[local] {} at line {}".format(imgk, lineno))
continue
if imgk in f_globals:
v = frame.f_globals[imgk]
# vhash = hash(v) # TypeError: unhashable type: 'numpy.ndarray'
vhash = hash(str(v))
if imgk in GLOBAL_HASH_DICT.keys():
if vhash == GLOBAL_HASH_DICT[imgk]:
print("{} is existed, hash={}, skipped".format(imgk, vhash))
continue
else:
print("{} is existed, old hash={}, new hash={}".format(imgk, GLOBAL_HASH_DICT[imgk], vhash))
GLOBAL_HASH_DICT[imgk] = vhash
cvlog.image(cvlog.Level.INFO, v, msg="[global] {} at line {}".format(imgk, lineno))
continue
# print(imgk + " not found") # 防止手动传一个不存在的值
return
def _check_is_image(items, tip="local", shape=None):
""" _shape传None的时候,取第一个符合要求的 """
if shape is None:
for k, v in items:
if type(v) == np.ndarray:
if len(v.shape) == 3 and v.shape[2] == 3:
check_shape = v.shape
print(("shape:", check_shape))
break
else:
check_shape = shape
try:
_rows, _cols = check_shape[:2]
except:
print("shape is invalid, maybe image is not existed.")
return
for k, v in items:
# print(k)
# print(type(v))
if type(v) == np.ndarray:
if len(v.shape) not in [2, 3]:
continue
if len(v.shape) == 3 and v.shape[2] != 3:
continue
# 对 _rows, _cols 的匹配,完全匹配貌似没必要
if v.shape[0] < _rows / 10:
continue
if v.shape[1] < _cols / 10:
continue
if tip == "global":
vhash = hash(str(v))
if k in GLOBAL_HASH_DICT.keys():
if vhash == GLOBAL_HASH_DICT[k]:
print("{} is existed, hash={}, skipped".format(k, vhash))
continue
else:
print("{} is existed, old hash={}, new hash={}".format(k, GLOBAL_HASH_DICT[k], vhash))
GLOBAL_HASH_DICT[k] = vhash
print("Line[{}]: [{}] {} is matched, shape is {}".format(tip, lineno, k, v.shape))
cvlog.image(cvlog.Level.INFO, v, msg="[{}] {} at line {}".format(tip, k, lineno))
shape = None
if base_image is not None:
shape = base_image.shape
# print(frame.f_globals.keys())
print(list(filter(lambda x: not x.startswith("__"), frame.f_globals.keys())))
_check_is_image(frame.f_globals.items(), shape=shape, tip="global")
if func != "<module>":
# print(frame.f_locals.items())
print(list(filter(lambda x: not x.startswith("__"), frame.f_locals.keys())))
_check_is_image(frame.f_locals.items(), shape=shape, tip="local")
################### 分界线 ###################
# test
def get_vars(frame_no=1):
frame = sys._getframe(frame_no)
print(frame.f_globals.items())
print(frame.f_locals.items())
# test wrapper
def show_caller(level=1):
def show(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print('{0.f_code.co_filename}:{0.f_lineno}'.format(sys._getframe(level)), "->", func.__name__)
return wrapper
return show
@show_caller(1)
def foo(): pass
# foo()
def yh_cv2_logger0(func): # 包两层,参数为func,不能传入自己的参数
# def mylog(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs) # 希望的是在func这里面的frame执行我的check_image_and_log()
check_image_and_log() # 但是实际上变成顺序执行,压根不在同一个栈帧
# check_image_and_log(frame_no=frame_no, base_image=base_image, images=images)
return result
return wrapper
# return mylog
# 装饰器的方式 # 包三层,最外层传递参数,第二层是接收func参数的装饰器
# 放弃了,sys._getframe 在装饰器里感觉有点无解,无法传递到符合预期的值
def yh_cv2_logger(frame_no=1, base_image=None, images=[]):
def mylog(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
check_image_and_log(frame_no=frame_no, base_image=base_image, images=images)
return result
return wrapper
return mylog
# https://blog.csdn.net/qq_39093583/article/details/126997392
class Hook:
"""
hook 方法,实例化后,获取调用链路上一个函数名及参数信息,call后执行函数
# 也想着按照这样的方式,在Hook里去调用check_image_and_log,但是栈帧始终不行,放弃。
"""
def __init__(self, obj: object()):
_ancestors = obj.__class__.mro()
_f_back = sys._getframe().f_back
self.cls_name = _f_back.f_code.co_name
self.kwargs = _f_back.f_locals
self.kwargs.pop('self')
if len(_ancestors) > 2: # 超过一层继承抛出异常
raise EnvironmentError(f'method: {self.cls_name} unimplemented')
def __call__(self, obj: object()):
return getattr(obj, self.cls_name)(**self.kwargs)
class Base:
def add(self, num):
return Hook(self)
class A(Base):
def __init__(self, result):
self.result = result
def add(self, num):
return self.result + num
if __name__ == '__main__':
b = Base()
h = b.add(23)
print(h.cls_name, h.kwargs)
a = A(10)
print(h(a))
cvlog\html_logger.py
修改了两个方法
def log_image(self, level, log_type, img_data, msg):
data = ''.join(['<img src="data:image/png;base64, ', img_data, '" style="max-width: 100%;"/>'])
self.__append_log_item(level, log_type, data, msg)
def __append_log_item(self, level, log_type, log_detail, msg):
short_stack, data = self.__get_log_info()
template = '<div class="quarter">'
template += '<div>' + data['time_stamp'] + '</div>'
if msg:
# template += '<div><pre id="description">[global] SRC2 at line 33</pre></div>'
template += '<div><pre">' + msg + '</pre></div>'
# template += '<div id="ld_log_data"><img src="1.jpg" style="max-width: 100%;"/></div>'
template += '<div>' + log_detail + '</div>'
template += '<div><pre>' + re.sub(r'^/', '', short_stack) + '</pre></div>'
template += '</div>'
self.__try_append([template])
cvlog\html_template.py 全面修改了
CONTENT_START = '<body><div class="log-container"><div class="log-lists"> '
CONTENT_END = '</div></body></html>'
NO_DATA_CONTENT = '<div id="no-data">No data logged</div>'
SCRIPT = '<script>/* No need */ </script>'
STYLE = '<style>body{width: 100%; height: 100%; margin: 0px; font-family:Arial, Helvetica, sans-serif;} .quarter{float: left;width: 25%;box-sizing: border-box;padding: 10px;min-width: 150px;} @media (max-width:615px ) {.quarter{float: left;width: 33%;box-sizing: border-box;padding: 10px;min-width: 150px;}} @media (max-width:465px ) {.quarter{float: left;width: 50%;box-sizing: border-box;padding: 10px;min-width: 150px;}} @media (max-width:315px ) {.quarter{float: left;width: 100%;box-sizing: border-box;padding: 10px;}}</style>'
Halcon那样的可视化工具 (matlab也有?)
visual studio的插件 Image Watch
https://blog.csdn.net/qq_39531155/article/details/113698915
pip install visual-logging pip install opencv-log