基于热成像的巡检和AidLux的工程方案

2023-11-22 14:30

本文主要是介绍基于热成像的巡检和AidLux的工程方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、热成像巡检介绍

输电线路巡检主要分为线路本体、附属设施、通道及电力保护区三大类。其中线路线路本体巡检内容包括绝缘子、金具以及导、地线等。特别的,绝缘子,顾名思义,是隔离导线与塔体,起绝缘作用。

输电线路运行过程中,由于内在或外在的原因,导致绝缘子串的温度异常,甚至导致低零值、零值等问题。

提示:什么是零值和低零值?

        绝缘子的电阻值应该达到相当的数量级才能保证绝缘作用。当绝缘子的电阻变得很小,就会出现低零值现象,当绝缘子电阻趋近于0时,就出现了零值问题。绝缘子出现低零值和零值,就基本丧失了绝缘作用。

解决方法:可以通过红外相机进行拍摄,对图片进行温度分析,判断绝缘子能否处于正常工作状态
        劣化的陶瓷绝缘子表现为低温、复合绝缘子表现为高温。
        在考虑由于绝缘子电压程U型分布,以及导线端电压高于塔头端等呈现的温度分布特征。通过检测、分析绝缘子串的温度信息,可以判断绝缘子是否出现工作异常

二、热成像巡检

本文使用目标检测网络对旋转后的部件进行定位,具体的网络训练由于数据集过大没有做,所以采用的是老师提供的pt模型。大家有需要可以根据r-retinanet网络自己训练一个。

接下来训练好的模型部署在Aidlux平台,所以需要将模型pt转换为onnx再转换为tflite导出onnx模型以后,我们需要对模型本身进行一定的精简。精简本质上是对生成的onnx模型中的多余参数进行精简,同时对一些结果恒为常量的算子进行优化

onnx导出得到tflite模型,具体代码如下:

def onnx2tflite(onnx_path):onnx_converter(onnx_model_path = onnx_path,need_simplify = False,output_path = os.path.dirname(onnx_path), target_formats = ['tflite'], # or ['keras'], ['keras', 'tflite']weight_quant = False,int8_model = False,int8_mean = None,int8_std = None,image_root = None)
def onnx_converter(onnx_model_path:str,  output_path:str=None, input_node_names:list=None, output_node_names:list=None,need_simplify:bool=True, target_formats:list = ['keras', 'tflite'],native_groupconv:bool=False,weight_quant:bool=False, int8_model:bool=False, image_root:str=None,int8_mean:list or float = [123.675, 116.28, 103.53], int8_std:list or float = [58.395, 57.12, 57.375])->float:if not isinstance(target_formats, list) and  'keras' not in target_formats and 'tflite' not in target_formats:raise KeyError("'keras' or 'tflite' should in list")model_proto = load_onnx_modelproto(onnx_model_path, input_node_names, output_node_names, need_simplify)keras_model = keras_builder(model_proto, native_groupconv)if 'tflite' in target_formats:tflite_model = tflite_builder(keras_model, weight_quant, int8_model, image_root, int8_mean, int8_std)onnx_path, model_name = os.path.split(onnx_model_path)if output_path is None:output_path = onnx_pathoutput_path = os.path.join(output_path, model_name.split('.')[0])keras_model_path = Noneif 'keras' in target_formats:keras_model_path = output_path + ".h5"keras_model.save(keras_model_path)LOG.info(f"keras model saved in {keras_model_path}")tflite_model_path = Noneif 'tflite' in target_formats:tflite_model_path = output_path + ".tflite"with open(tflite_model_path, "wb") as fp:fp.write(tflite_model)convert_result = {"keras":keras_model_path, "tflite":tflite_model_path, "keras_error":0, "tflite_error":0}# ignore quantization modelif int8_model:return convert_resulterror_dict = {}try:error_dict = get_elements_error(model_proto, keras_model_path, tflite_model_path)keras_error, tflite_error = error_dict.get("keras", None), error_dict.get("tflite", None)if keras_error:if keras_error > 1e-2:LOG.error("h5 model elements' max error has reached {:^.4E}, but convert is done, please check {} carefully!".format(keras_error, keras_model_path))elif keras_error > 1e-4:LOG.warning("h5 model elements' max error is {:^.4E}, pass, h5 saved in {}".format(keras_error, keras_model_path))else:LOG.info("h5 model elements' max error is {:^.4E}, pass, h5 saved in {}".format(keras_error, keras_model_path))if tflite_error:if tflite_error > 1e-2:LOG.error("tflite model elements' max error has reached {:^.4E}, but convert is done, please check {} carefully!".format(tflite_error, tflite_model_path))elif tflite_error > 1e-4:LOG.warning("tflite model elements' max error is {:^.4E}, pass, tflite saved in {}".format(tflite_error, tflite_model_path))else:LOG.info("tflite model elements' max error is {:^.4E}, pass, tflite saved in {}".format(tflite_error, tflite_model_path))except:LOG.warning("convert is successed, but model running is failed, please check carefully!")convert_result["keras_error"] = error_dict.get("keras", None)convert_result["tflite_error"] = error_dict.get("tflite", None)return convert_result

 导出模型成功后对tflite进行测试

if __name__=='__main__':tflite_model = r"D:\BaiduNetdiskDownload\Lesson3_Training_and_Deploy\Lesson3_Training_and_Deploy\r-retinanet.tflite"          # [SAI-KEY] 指定tflite模型路径image_path = r'D:\BaiduNetdiskDownload\Lesson3_Training_and_Deploy\Lesson3_Training_and_Deploy\AidLux_Deploy\AidLux_Deploy\samples\000001.jpg'  # [SAI-KEY] 指定测试样本路径tflite_model = tf.lite.Interpreter(tflite_model) # Load tflite modeltflite_model.allocate_tensors()tflife_input_details = tflite_model.get_input_details()    # 输入节点描述.tflife_output_details = tflite_model.get_output_details()  # 输出节点描述.# 输入预处理img = cv2.imread(image_path)im, im_scales = process_img(img, NCHW=False, ToTensor=False)# 设定输入tflite_model.set_tensor(tflife_input_details[0]['index'], im)# 推理tflite_model.invoke()# 捕获推理输出outputs = tflite_model.get_tensor(tflife_output_details[0]['index'])output = np.transpose(outputs, (0, 2, 1))  # .astype(np.float32)im_anchor = np.transpose(im, (0, 3, 1, 2)).astype(np.float32)# 构造Anchor信息anchors_list = []anchor_generator = Anchors(ratios = np.array([0.2, 0.5, 1, 2, 5]))original_anchors = anchor_generator(im_anchor)   # (bs, num_all_achors, 5)anchors_list.append(original_anchors)# 后解算decode_output = decoder(im_anchor, anchors_list[-1], output[..., 5:8], output[..., 0:5], thresh=0.5, nms_thresh=0.2, test_conf=None)# 重构解算scores = decode_output[0].reshape(-1, 1)classes = decode_output[1].reshape(-1, 1)boxes = decode_output[2]boxes[:, :4] = boxes[:, :4] / im_scalesif boxes.shape[1] > 5:   boxes[:, 5:9] = boxes[:, 5:9] / im_scalesdets = np.concatenate([classes, scores, boxes], axis=1)# 过滤输出keep = np.where(classes > 0)[0]dets =  dets[keep, :]# 转换坐标形式 'xywha' to 'xyxyxyxy'res = sort_corners(rbox_2_quad(dets[:, 2:]))# 写本地out_file = image_path.replace('.jpg', '.txt')with codecs.open(out_file, 'w', 'utf-8') as f:if dets.shape[0] == 0:f.close()else:for k in range(dets.shape[0]):f.write('{:.0f} {:.0f} {:.0f} {:.0f} {:.0f} {:.0f} {:.0f} {:.0f} {} {} {:.2f}\n'.format(res[k, 0], res[k, 1], res[k, 2], res[k, 3],res[k, 4], res[k, 5], res[k, 6], res[k, 7],dets[k, 0], Path(image_path).stem, dets[k, 1],)# (x, y, x, y, x, y, x, y, class, image_name, score))# cv绘图for k in range(dets.shape[0]):cv2.line(img, (int(res[k, 0]), int(res[k, 1])), (int(res[k, 2]), int(res[k, 3])), (0, 255, 0), 3)cv2.line(img, (int(res[k, 2]), int(res[k, 3])), (int(res[k, 4]), int(res[k, 5])), (0, 255, 0), 3)cv2.line(img, (int(res[k, 4]), int(res[k, 5])), (int(res[k, 6]), int(res[k, 7])), (0, 255, 0), 3)cv2.line(img, (int(res[k, 6]), int(res[k, 7])), (int(res[k, 0]), int(res[k, 1])), (0, 255, 0), 3)cv2.imwrite(image_path.replace('.jpg', '_eval.jpg'), img)

如果输出为下图则表示转换tflite成功

三、AidLux平台部署

对于开发者而言,AI项目中各种算法的数据集准备+模型训练+模型部署依然存在着不小的难度。AidLux的出现,可以将我们的安卓设备以非虚拟的形式变成同时拥有Android和Linux系统环境的边缘计算设备,支持主流AI框架,非常易于部署,还有专门的接口调度算力资源,极大地降低了AI应用落地门槛。

def process_img(img, target_size=640, max_size=2000, multiple=32, keep_ratio=True, NCHW=True, ToTensor=True):img = cv2.resize(img, (640, 512), interpolation=cv2.INTER_LINEAR)im_shape = img.shapeim_size_min = np.min(im_shape[0:2])im_size_max = np.max(im_shape[0:2])# resize with keep_ratioif keep_ratio:im_scale = float(target_size) / float(im_size_min)  if np.round(im_scale * im_size_max) > max_size:     im_scale = float(max_size) / float(im_size_max)im_scale_x = np.floor(img.shape[1] * im_scale / multiple) * multiple / img.shape[1]im_scale_y = np.floor(img.shape[0] * im_scale / multiple) * multiple / img.shape[0]image_resized = cv2.resize(img, None, None, fx=im_scale_x, fy=im_scale_y, interpolation=cv2.INTER_LINEAR)im_scales = np.array([im_scale_x, im_scale_y, im_scale_x, im_scale_y])im = image_resized / 255.0  # np.float64im = im.astype(np.float32)PIXEL_MEANS =(0.485, 0.456, 0.406)    # RGB  format mean and variancesPIXEL_STDS = (0.229, 0.224, 0.225)im -= np.array(PIXEL_MEANS)im /= np.array(PIXEL_STDS)im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)  # BGR2RGBif NCHW:im = np.transpose(im, (2, 0, 1)).astype(np.float32)  # [SAI-KEY] TensorFlow use input with NHWC.im = im[np.newaxis, ...]if ToTensor:im = torch.from_numpy(im)return im, im_scaleselse:return None
if __name__=="__main__":cap = cvs.VideoCapture(0)frame_id = 0while True:frame = cap.read()if frame is None:continueframe_id += 1if frame_id % 3 != 0:continuetime0 = time.time()# 预处理im, im_scales = process_img(frame, NCHW=False, ToTensor=False)  # im: NHWC#img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)# img /= 255''' 定义输入输出shape '''in_shape = [1 * 640 * 800 * 3 * 4]  # HWC, float32out_shape = [1 * 53325 * 8 * 4]  # 8400: total cells, 52 = 48(num_classes) + 4(xywh), float32#out_shape = [1 * 55425 * 8 * 4]  # 8400: total cells, 52 = 48(num_classes) + 4(xywh), float32''' AidLite初始化 '''aidlite = aidlite_gpu.aidlite()''' 加载R-RetinaNet模型 '''tflite_model = '/home/AidLux_Deploy/models/r-retinanet.tflite'res = aidlite.ANNModel(tflite_model, in_shape, out_shape, 4, -1) # Infer on -1: cpu, 0: gpu, 1: mixed, 2: dsp''' 设定输入输出 '''aidlite.setInput_Float32(im, 640, 800)''' 启动推理 '''aidlite.invoke()''' 捕获输出 '''preds = aidlite.getOutput_Float32(0)#preds = preds.reshape(1, 8, 53325)preds = preds.reshape(1, 8, (int)(preds.shape[0]/8))output = np.transpose(preds, (0, 2, 1))''' 创建Anchor '''im_anchor = np.transpose(im, (0, 3, 1, 2)).astype(np.float32)anchors_list = []anchor_generator = Anchors(ratios = np.array([0.2, 0.5, 1, 2, 5]))original_anchors = anchor_generator(im_anchor)   # (bs, num_all_achors, 5)anchors_list.append(original_anchors)''' 解算输出 '''decode_output = decoder(im_anchor, anchors_list[-1], output[..., 5:8], output[..., 0:5], thresh=0.5, nms_thresh=0.2, test_conf=None)for i in range(len(decode_output)):print("dim({}), shape: {}".format(i, decode_output[i].shape))''' 重构输出 '''scores = decode_output[0].reshape(-1, 1)classes = decode_output[1].reshape(-1, 1)boxes = decode_output[2]boxes[:, :4] = boxes[:, :4] / im_scalesif boxes.shape[1] > 5:   boxes[:, 5:9] = boxes[:, 5:9] / im_scalesdets = np.concatenate([classes, scores, boxes], axis=1)''' 过滤类别 '''keep = np.where(classes > 0)[0]dets =  dets[keep, :]''' 转换坐标('xyxya'->'xyxyxyxy') '''res = sort_corners(rbox_2_quad(dets[:, 2:]))''' 评估绘图 '''for k in range(dets.shape[0]):cv2.line(frame, (int(res[k, 0]), int(res[k, 1])), (int(res[k, 2]), int(res[k, 3])), (0, 255, 0), 3)cv2.line(frame, (int(res[k, 2]), int(res[k, 3])), (int(res[k, 4]), int(res[k, 5])), (0, 255, 0), 3)cv2.line(frame, (int(res[k, 4]), int(res[k, 5])), (int(res[k, 6]), int(res[k, 7])), (0, 255, 0), 3)cv2.line(frame, (int(res[k, 6]), int(res[k, 7])), (int(res[k, 0]), int(res[k, 1])), (0, 255, 0), 3)cvs.imshow(frame)

 具体实现代码如上所示,这个代码是aidlux实现摄像头提取目标区域的,实现效果如下

目标检测

如果使用本地图片实现代码

具体实现结果 

这篇关于基于热成像的巡检和AidLux的工程方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/410808

相关文章

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

在Java中将XLS转换为XLSX的实现方案

《在Java中将XLS转换为XLSX的实现方案》在本文中,我们将探讨传统ExcelXLS格式与现代XLSX格式的结构差异,并为Java开发者提供转换方案,通过了解底层原理、性能优势及实用工具,您将掌握... 目录为什么升级XLS到XLSX值得投入?实际转换过程解析推荐技术方案对比Apache POI实现编程

Java实现本地缓存的常用方案介绍

《Java实现本地缓存的常用方案介绍》本地缓存的代表技术主要有HashMap,GuavaCache,Caffeine和Encahche,这篇文章主要来和大家聊聊java利用这些技术分别实现本地缓存的方... 目录本地缓存实现方式HashMapConcurrentHashMapGuava CacheCaffe

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

MyBatisX逆向工程的实现示例

《MyBatisX逆向工程的实现示例》本文主要介绍了MyBatisX逆向工程的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录逆向工程准备好数据库、表安装MyBATisX插件项目连接数据库引入依赖pom.XML生成实体类、