基于热成像的巡检和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

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

如何选择SDR无线图传方案

在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传输。OpenHD项目提供了一个完整的工具链,包括发射器和接收器的硬件设计以及相应的软件。 2. **USRP(Universal Software Radio Periphera

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

家庭和学生用户笔记本电脑配置方案

2.6.1  家庭和学生用户笔记本电脑配置方案   2.6.1  家庭和学生用户笔记本电脑配置方案   普通家庭用户、学生用户主要用于上网、娱乐、学习等,这类用户要求笔记本电脑的各方面 功能比较均衡。在选购此类笔记本电脑时,主要考虑外观设计方面要比较时尚,而且性能上也要 够强,一些大型复杂的软件以及目前的主流游戏都要能够流畅地运行才行。   对于CPU方面,可以考虑目前主流的第二