超詳細避坑指南!OrangpiAIPro轉換部署模型全流程!

目錄

OrangepiPro初體驗

前述:

一、硬件準備

二、安裝CANN工具鏈(虛擬機)

三、配置模型轉換環境(虛擬機)

1.安裝miniconda 。

2.創建環境。

3.安裝依賴包

四、轉換模型

1. 查看設備號(開發板)

2. 使用ATC命令轉換onnx模型為om模型(虛擬機)

補:使用ATC命令時遇到問題

五、模型推理(開發板)

1. 在板端安裝CANN

2. 安裝Mindx,用于推理。

3. 使用conda創建虛擬環境- python=3.9

4. python推理代碼。

六、效果展示(開發板)

七、總結


OrangepiPro初體驗

?? 終于!懷著激動的心情拿到了期待已久的開發板,迫不及待趕緊拆箱,映入眼簾的只有一個字:酷!正如下面幾個大字所寫:為AI而生。該開發板搭載華為昇騰AI處理器。能覆蓋生態開發板者的主流應用場景,讓用戶實踐各種創新場景,并為其提供配套的軟硬件。豐富的接口更是賦予了Orange Pi AIpro強大的可拓展性。包括兩個HDMI輸出、GPIO接口、Type-C電源接口、支持SATA/NVMe SSD 2280的M.2插槽、TF插槽、千兆網口、兩個USB3.0、一個USB Type-C 3.0、一個Micro USB、兩個MIPI攝像頭、一個MIPI屏等,預留電池接口。在操作系統方面,Orange Pi AIpro可運行Ubuntu、openEuler操作系統,滿足大多數AI算法原型驗證、推理應用開發的需求。實物如下:

在這里插入圖片描述

在這里插入圖片描述

前述:

?? 本文將不再介紹獲取ip、連接wifi、vnc等操作,詳情查看OrangpiPro官方手冊即可。官方地址。
?? 作者認為后續的進一步學習或開發都應該建立在有基本了解的前提下,所以本文的宗旨就是帶剛入門的初級開發者實現模型部署的完整流程。且本文內容還涉及在部署模型時所遇到的問題及其解決方法。每一步都有詳細的步驟,避免踩坑。對剛入門進行學習的開發者來說,簡直是不要太友好。相信根據本文部署完成后,會對流程有一些較為清楚的認識,對以后其他模型部署以及學習會有很大的幫助。創造不易,且看且珍惜。

一、硬件準備

Ubuntu22.04_x86系統(虛擬機)
OrangepiPro開發板

二、安裝CANN工具鏈(虛擬機)

??異構計算架構CANN是華為針對AI場景推出的異構計算架構,向上支持多種AI框架,包括MindSpore、PyTorch、TensorFlow等,向下服務AI處理器與編程,發揮承上啟下的關鍵作用,是提升昇騰AI處理器計算效率的關鍵平臺。所以CANN工具鏈是我們必備工具鏈。打開ubuntu的瀏覽器:資源下載地址。
在這里插入圖片描述

下載完成后,自動保存在Downloads目錄下,如下所示:
在這里插入圖片描述

?? 這里我已經給軟件包添加了執行權限,如果初次下載請使用添加可執行權限。后續使用安裝命令進行安裝。安裝命令:?./Ascend-cann-toolkit_7.0.RC1_linux-x86_64.run --install?。安裝完成后,配置環境變量。使用命令:vi ~/.bashrc。將下述命令粘貼到文件里,這樣就可以永久有效使用了,而不是只對當前命令窗口有效。

source /home/qjl/Ascend/ascend-toolkit/set_env.sh
export LD_LIBRARY_PATH=/home/qjl/Ascend/ascend-toolkit/7.0.RC1/x86_64-linux/devlib/x86_64:$LD_LIBRARY_PATH

?? 添加成功后,使用source ~/.bashrc命令來刷新使得文件配置生效。此時我們就可以使用atc命令來轉換模型咯!如下,出現下面內容說明我們atc命令可以使用。
在這里插入圖片描述

三、配置模型轉換環境(虛擬機)

1.安裝miniconda 。

//linux_x86架構下的conda
wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.12.0-Linux-x86_64.sh
bash Miniconda3-py37_4.12.0-Linux-x86_64.sh

2.創建環境。

?? 這里使用conda來創建環境,這里我創建的為python 3.9版本。創建環境流程這里就不多贅述,具體詳情查看創建環境教程。

3.安裝依賴包

pip install attrs numpy decorator sympy cffi pyyaml pathlib2 psutil protobuf scipy requests absl-py wheel typing_extensions -i https://mirrors.huaweicloud.com/repository/pypi/simple

這里安裝完成后,如果哪些包出現依賴問題,則單獨裝一下該包即可。

四、轉換模型

1. 查看設備號(開發板)

?? 使用命令:npu-smi info,查看設備號這個操作是在開發板上進行的,上面的操作都是在ubuntu上進行的(當然也可以在開發板上進行,只不過本文演示是在ubuntu_x86)。
在這里插入圖片描述

2. 使用ATC命令轉換onnx模型為om模型(虛擬機)

atc --model=/home/qjl/cup.onnx --framework=5 --output=/home/qjl/cup --soc_version=Ascend310B4 

該命令的具體參數這里不多介紹,詳情請查看官方手冊即可。
我們使用完命令后,等待幾分鐘轉換好om模型。此時大功告成!廢話不多說,立馬部署到開發板上!

補:使用ATC命令時遇到問題

問題一:
在這里插入圖片描述
?? 這個情況說明內存崩潰。這個問題原以為是因為訓練模型的時候num_worker數量太大導致的問題,于是修改num_worker=0重新訓練模型,將模型導入linux中轉換時還是出現該錯誤,一時不知如何是好。但最終還是找到解決辦法,將下面命令導入環境變量。設置最大核心數即可。編譯過程僅使用一個核心,為了避免由于使用過多核心導致的資源競爭或內存不足問題。

export TE_PARALLEL_COMPILER=1
export MAX_COMPILE_CORE_NUMBER=1

這里和上面設置環境變量一樣,可以設置到~/.bashrc中,使其永久生效。

問題二:
在這里插入圖片描述
?? 找不到<type_traits>(C++庫),這是因為缺失C++庫導致的。于是我搜索本地gcc及g++庫,結果發現還沒有安裝編譯器,如下所示。
在這里插入圖片描述
?? 既然這樣,我們使用命令:sudo apt install build-essential,來安裝編譯工具包。這個工具包里包含了編譯時所需要的各種工具以及相應的庫文件。安裝完成以后,我們就可以使用之前的命令進行模型轉換咯~

五、模型推理(開發板)

1. 在板端安裝CANN

在這里插入圖片描述
?? 使用命令?./Ascend-cann-toolkit_7.0.RC1_linux-aarch64.run --install進行安裝。安裝完成后,和在linux_x86端一樣設置環境變量等操作,這里不再贅述。

2. 安裝Mindx,用于推理。

注意:這里只有當安裝好CANN后再進行安裝Mindx!
在這里插入圖片描述

?? 下載好以后,執行?./Ascend-mindxsdk-mxvision_6.0.RC1_linux-aarch64.run --install進行安裝。
?? 安裝完成后vi ~/.bashrc,添加source /home/HwHiAiUser/Mindx/mxVision/set_env.sh。添加完成后使用source ~/.bashrc使得文件生效。

3. 使用conda創建虛擬環境- python=3.9

//arm架構下的conda
wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.9.2-Linux-aarch64.sh
bash Miniconda3-py37_4.9.2-Linux-aarch64.sh

(1)安裝opencv:pip install opencv-python
(2)安裝numpy:pip install numpy
(3)安裝torch以及torchvision。下載好whl文件安裝即可。點擊:下載地址。如果缺少哪個包就再pip安裝一下即可。
在這里插入圖片描述

(4)安裝mindx包。
進入Mindx安裝目錄,路徑如下。找到whl文件使用pip進行安裝即可。
在這里插入圖片描述

4. python推理代碼。

(1)后處理代碼(公用)

def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=False, scaleFill=False, scaleup=True):# Resize image to a 32-pixel-multiple rectangle https://github.com/ultralytics/yolov3/issues/232shape = img.shape[:2]  # current shape [height, width]if isinstance(new_shape, int):new_shape = (new_shape, new_shape)# Scale ratio (new / old)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])if not scaleup:  # only scale down, do not scale up (for better test mAP)r = min(r, 1.0)# Compute paddingratio = r, r  # width, height ratiosnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh paddingif auto:  # minimum rectangledw, dh = np.mod(dw, 64), np.mod(dh, 64)  # wh paddingelif scaleFill:  # stretchdw, dh = 0.0, 0.0new_unpad = (new_shape[1], new_shape[0])ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]  # width, height ratiosdw /= 2  # divide padding into 2 sidesdh /= 2if shape[::-1] != new_unpad:  # resizeimg = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))left, right = int(round(dw - 0.1)), int(round(dw + 0.1))img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add borderreturn img, ratio, (dw, dh)def non_max_suppression(prediction,conf_thres=0.25,iou_thres=0.45,classes=None,agnostic=False,multi_label=False,labels=(),max_det=300,nm=0,  # number of masks
):"""Non-Maximum Suppression (NMS) on inference results to reject overlapping detectionsReturns:list of detections, on (n,6) tensor per image [xyxy, conf, cls]"""if isinstance(prediction, (list, tuple)):  # YOLOv5 model in validation model, output = (inference_out, loss_out)prediction = prediction[0]  # select only inference outputdevice = prediction.devicemps = 'mps' in device.type  # Apple MPSif mps:  # MPS not fully supported yet, convert tensors to CPU before NMSprediction = prediction.cpu()bs = prediction.shape[0]  # batch sizenc = prediction.shape[2] - nm - 5  # number of classesxc = prediction[..., 4] > conf_thres  # candidates# Checksassert 0 <= conf_thres <= 1, f'Invalid Confidence threshold {conf_thres}, valid values are between 0.0 and 1.0'assert 0 <= iou_thres <= 1, f'Invalid IoU {iou_thres}, valid values are between 0.0 and 1.0'# Settings# min_wh = 2  # (pixels) minimum box width and heightmax_wh = 7680  # (pixels) maximum box width and heightmax_nms = 30000  # maximum number of boxes into torchvision.ops.nms()time_limit = 0.5 + 0.05 * bs  # seconds to quit aftermulti_label &= nc > 1  # multiple labels per box (adds 0.5ms/img)t = time.time()mi = 5 + nc  # mask start indexoutput = [torch.zeros((0, 6 + nm), device=prediction.device)] * bsfor xi, x in enumerate(prediction):  # image index, image inference# Apply constraints# x[((x[..., 2:4] < min_wh) | (x[..., 2:4] > max_wh)).any(1), 4] = 0  # width-heightx = x[xc[xi]]  # confidence# Cat apriori labels if autolabellingif labels and len(labels[xi]):lb = labels[xi]v = torch.zeros((len(lb), nc + nm + 5), device=x.device)v[:, :4] = lb[:, 1:5]  # boxv[:, 4] = 1.0  # confv[range(len(lb)), lb[:, 0].long() + 5] = 1.0  # clsx = torch.cat((x, v), 0)# If none remain process next imageif not x.shape[0]:continue# Compute confx[:, 5:] *= x[:, 4:5]  # conf = obj_conf * cls_conf# Box/Maskbox = xywh2xyxy(x[:, :4])  # center_x, center_y, width, height) to (x1, y1, x2, y2)mask = x[:, mi:]  # zero columns if no masks# Detections matrix nx6 (xyxy, conf, cls)if multi_label:i, j = (x[:, 5:mi] > conf_thres).nonzero(as_tuple=False).Tx = torch.cat((box[i], x[i, 5 + j, None], j[:, None].float(), mask[i]), 1)else:  # best class onlyconf, j = x[:, 5:mi].max(1, keepdim=True)x = torch.cat((box, conf, j.float(), mask), 1)[conf.view(-1) > conf_thres]# Filter by classif classes is not None:x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]# Check shapen = x.shape[0]  # number of boxesif not n:  # no boxescontinueelif n > max_nms:  # excess boxesx = x[x[:, 4].argsort(descending=True)[:max_nms]]  # sort by confidenceelse:x = x[x[:, 4].argsort(descending=True)]  # sort by confidence# Batched NMSc = x[:, 5:6] * (0 if agnostic else max_wh)  # classesboxes, scores = x[:, :4] + c, x[:, 4]  # boxes (offset by class), scoresi = torchvision.ops.nms(boxes, scores, iou_thres)  # NMSif i.shape[0] > max_det:  # limit detectionsi = i[:max_det]output[xi] = x[i]if mps:output[xi] = output[xi].to(device)if (time.time() - t) > time_limit:print(f'WARNING ?? NMS time limit {time_limit:.3f}s exceeded')break  # time limit exceededreturn outputdef xywh2xyxy(x):# Convert nx4 boxes from [x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-righty = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)y[:, 0] = x[:, 0] - x[:, 2] / 2  # top left xy[:, 1] = x[:, 1] - x[:, 3] / 2  # top left yy[:, 2] = x[:, 0] + x[:, 2] / 2  # bottom right xy[:, 3] = x[:, 1] + x[:, 3] / 2  # bottom right yreturn ydef get_labels_from_txt(path):labels_dict = dict()with open(path) as f:for cat_id, label in enumerate(f.readlines()):labels_dict[cat_id] = label.strip()return labels_dictdef scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):# Rescale coords (xyxy) from img1_shape to img0_shapeif ratio_pad is None:  # calculate from img0_shapegain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])  # gain  = old / newpad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2  # wh paddingelse:gain = ratio_pad[0][0]pad = ratio_pad[1]coords[:, [0, 2]] -= pad[0]  # x paddingcoords[:, [1, 3]] -= pad[1]  # y paddingcoords[:, :4] /= gainclip_coords(coords, img0_shape)return coordsdef clip_coords(boxes, shape):# Clip bounding xyxy bounding boxes to image shape (height, width)if isinstance(boxes, torch.Tensor):  # faster individuallyboxes[:, 0].clamp_(0, shape[1])  # x1boxes[:, 1].clamp_(0, shape[0])  # y1boxes[:, 2].clamp_(0, shape[1])  # x2boxes[:, 3].clamp_(0, shape[0])  # y2else:  # np.array (faster grouped)boxes[:, [0, 2]] = boxes[:, [0, 2]].clip(0, shape[1])  # x1, x2boxes[:, [1, 3]] = boxes[:, [1, 3]].clip(0, shape[0])  # y1, y2def nms(box_out, conf_thres=0.4, iou_thres=0.5):try:boxout = non_max_suppression(box_out, conf_thres=conf_thres, iou_thres=iou_thres, multi_label=True)except:boxout = non_max_suppression(box_out, conf_thres=conf_thres, iou_thres=iou_thres)return boxout

(2)圖片推理:將模型文件和圖片、以及推理代碼放在一個目錄下。運行該文件即可。

# coding=utf-8
import cv2  # 圖片處理三方庫,用于對圖片進行前后處理
import numpy as np  # 用于對多維數組進行計算
import torch  # 深度學習運算框架,此處主要用來處理數據
import time
import torchvision
from mindx.sdk import Tensor  # mxVision 中的 Tensor 數據結構
from mindx.sdk import base  # mxVision 推理接口def draw_bbox(bbox, img0, color, wt, names):det_result_str = ''for idx, class_id in enumerate(bbox[:, 5]):if float(bbox[idx][4] < float(0.05)):continueimg0 = cv2.rectangle(img0, (int(bbox[idx][0]), int(bbox[idx][1])), (int(bbox[idx][2]), int(bbox[idx][3])), color, wt)img0 = cv2.putText(img0, str(idx) + ' ' + names[int(class_id)], (int(bbox[idx][0]), int(bbox[idx][1] + 16)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)img0 = cv2.putText(img0, '{:.4f}'.format(bbox[idx][4]), (int(bbox[idx][0]), int(bbox[idx][1] + 32)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)det_result_str += '{} {} {} {} {} {}\n'.format(names[bbox[idx][5]], str(bbox[idx][4]), bbox[idx][0], bbox[idx][1], bbox[idx][2], bbox[idx][3])return img0if __name__ == '__main__':# 初始化資源和變量base.mx_init()  # 初始化 mxVision 資源DEVICE_ID = 0  # 設備idmodel_path = 'best.om'  # 模型路徑image_path = 'image.jpg'  # 測試圖片路徑# 數據前處理img_bgr = cv2.imread(image_path, cv2.IMREAD_COLOR)  # 讀入圖片img, scale_ratio, pad_size = letterbox(img_bgr, new_shape=[640, 640])  # 對圖像進行縮放與填充,保持長寬比img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, HWC to CHWimg = np.expand_dims(img, 0).astype(np.float32)  # 將形狀轉換為 channel first (1, 3, 640, 640),即擴展第一維為 batchsizeimg = np.ascontiguousarray(img) / 255.0  # 轉換為內存連續存儲的數組img = Tensor(img) # 將numpy轉為轉為Tensor類# 模型推理, 得到模型輸出model = base.model(modelPath=model_path, deviceId=DEVICE_ID)  # 初始化 base.model 類output = model.infer([img])[0]  # 執行推理。輸入數據類型:List[base.Tensor], 返回模型推理輸出的 List[base.Tensor]# 后處理output.to_host()  # 將 Tensor 數據轉移到內存output = np.array(output)  # 將數據轉為 numpy array 類型boxout = nms(torch.tensor(output), conf_thres=0.4, iou_thres=0.5)  # 利用非極大值抑制處理模型輸出,conf_thres 為置信度閾值,iou_thres 為iou閾值pred_all = boxout[0].numpy()  # 轉換為numpy數組scale_coords([640, 640], pred_all[:, :4], img_bgr.shape, ratio_pad=(scale_ratio, pad_size))  # 將推理結果縮放到原始圖片大小labels_dict = get_labels_from_txt('./coco_names.txt')  # 得到類別信息,返回序號與類別對應的字典img_dw = draw_bbox(pred_all, img_bgr, (0, 255, 0), 2, labels_dict)  # 畫出檢測框、類別、概率# 保存圖片到文件cv2.imwrite('result.png', img_dw)print('save infer result success'
import cv2
import numpy as np
import torch
import time
import torchvision
from mindx.sdk import Tensor
from mindx.sdk import base# 這里包括你已經提供的所有函數
# letterbox, non_max_suppression, xywh2xyxy, get_labels_from_txt, scale_coords, clip_coords, nmsdef draw_bbox(bbox, img0, color, wt, names):det_result_str = ''for idx, class_id in enumerate(bbox[:, 5]):if float(bbox[idx][4] < float(0.05)):continueimg0 = cv2.rectangle(img0, (int(bbox[idx][0]), int(bbox[idx][1])), (int(bbox[idx][2]), int(bbox[idx][3])), color, wt)img0 = cv2.putText(img0, str(idx) + ' ' + names[int(class_id)], (int(bbox[idx][0]), int(bbox[idx][1] - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)img0 = cv2.putText(img0, '{:.2f}'.format(bbox[idx][4]), (int(bbox[idx][0]), int(bbox[idx][1] - 30)), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)det_result_str += '{} {} {} {} {} {}\n'.format(names[bbox[idx][5]], str(bbox[idx][4]), bbox[idx][0], bbox[idx][1], bbox[idx][2], bbox[idx][3])return img0def process_frame(frame, model, labels_dict, scale_ratio, pad_size, input_shape=(640, 640)):img, _, _ = letterbox(frame, new_shape=input_shape)img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, HWC to CHWimg = np.expand_dims(img, 0).astype(np.float32)  # batch size 1img = np.ascontiguousarray(img) / 255.0img = Tensor(img)output = model.infer([img])[0]output.to_host()output = np.array(output)boxout = nms(torch.tensor(output), conf_thres=0.4, iou_thres=0.5)pred_all = boxout[0].numpy()scale_coords(input_shape, pred_all[:, :4], frame.shape, ratio_pad=(scale_ratio, pad_size))img_with_boxes = draw_bbox(pred_all, frame, (0, 255, 0), 2, labels_dict)return img_with_boxesif __name__ == '__main__':# 初始化資源和變量base.mx_init()DEVICE_ID = 0model_path = 'best.om'video_path = 'video.mp4'output_video_path = 'result_video.mp4'# 初始化視頻讀取與寫入cap = cv2.VideoCapture(video_path)fourcc = cv2.VideoWriter_fourcc(*'mp4v')fps = int(cap.get(cv2.CAP_PROP_FPS))frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))out = cv2.VideoWriter(output_video_path, fourcc, fps, (frame_width, frame_height))# 讀取類別標簽labels_dict = get_labels_from_txt('./coco_names.txt')# 加載模型model = base.model(modelPath=model_path, deviceId=DEVICE_ID)while cap.isOpened():ret, frame = cap.read()if not ret:break# 數據前處理img_bgr = frameimg, scale_ratio, pad_size = letterbox(img_bgr, new_shape=[640, 640])# 處理幀processed_frame = process_frame(frame, model, labels_dict, scale_ratio, pad_size)# 寫入處理后的幀out.write(processed_frame)# 釋放資源cap.release()out.release()print('Video processing complete. Saved to', output_video_path)

遇到問題
在這里插入圖片描述
?? 我們在運行推理代碼時出現上述問題,原因是因為我們torch和torchvision的版本有點高,只需要降低版本即可。如使用torch==1.10.0 torchvision==0.11.0即可。當然這里不影響我們最后的結果,所以覺得煩的小伙伴可以降低版本,該問題就解決了。

六、效果展示(開發板)

在這里插入圖片描述

圖片推理結果:
在這里插入圖片描述

視頻推理結果:
在這里插入圖片描述

七、總結

??這里我們使用自訓練的車輛數據集模型,部署到開發板上可見效果很好,這里我們就完成了從0到1的全部流程,中間也遇到很多問題,也是通過查閱大量資料來解決的問題,這也是必備的學習方法之一。本人也是處于學習階段,所以有錯誤的地方,希望各位積極指正,我們一起加油。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17279.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17279.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17279.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一步一腳印:輕松掌握服務器硬件的奧秘

在這個信息化飛速發展的時代&#xff0c;無論是企業還是個人&#xff0c;對數據處理和存儲的需求日益增長。服務器&#xff0c;作為互聯網的基石&#xff0c;其重要性不言而喻。但對于大多數人來說&#xff0c;服務器的內部世界似乎既復雜又遙遠。不過&#xff0c;不用擔心&…

在Anaconda中修改查找和安裝軟件包的存儲庫的來源channels

以下是一些關鍵的步驟和命令&#xff0c;用于修改Anaconda的channels&#xff1a; 查看當前channels 使用命令 conda config --show channels 可以查看當前配置的channels。 添加新的channel 使用命令 conda config --add channels <channel_url> 來添加一個新的channel…

TIM定時器PWM輸出

tim.c #include "tim.h" #include "stm32mp1xx_tim.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"//tim4初始化(蜂鳴器) void tim4_init(){//1.使能GPIOB的外設時鐘RCC->MP_AHB4ENSETR | (0x1<<1);//使能TI…

辦公必備!一鍵拆分文件,效率翻倍的秘密

需求介紹 1、我有一張數據表“測試數據.xlsx” 2、我要根據A1“COUNTY_CODE”分類拆分成幾張數據表&#xff08;這里從9657到9658共12類&#xff0c;就是拆分成12張數據表&#xff09; 3、根據12個分類&#xff0c;發送數據郵件給對應的收件人 4、收件人及抄送人、共同抄送人…

Appium系列(2)元素定位工具appium-inspector

背景 如實現移動端自動化&#xff0c;依賴任何工具時&#xff0c;都需要針對于頁面中的元素進行識別&#xff0c;通過識別到指定的元素&#xff0c;對元素進行事件操作。 識別元素的工具為appium官網提供的appium-inspector。 appium-inspector下載地址 我這里是mac電腦需要下…

基于Cloudflare/CloudDNS/GitHub使用免費域名部署NewBing的AI服務

部署前準備&#xff1a; Cloudflare 賬號 https://dash.cloudflare.com/login CloudDNS 賬號 https://www.cloudns.net/ GitHub 賬號 https://github.com/Harry-zklcdc/go-proxy-bingai Cloudflare 部署 Worker CloudDNS 獲取免費二級域名 GitHub New Bing Ai 項目 https://git…

揭秘黃金分割數列:斐波那契數列的奇妙之旅

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、黃金分割數列——斐波那契數列的簡介 二、實現斐波那契數列的函數 三、斐波那契數列在…

前端開發之xlsx的使用和實例,并導出多個sheet

前端開發之xlsx的使用和實例 前言效果圖1、安裝2、在頁面中引用3、封裝工具類&#xff08;excel.js&#xff09;4、在vue中使用 前言 在實現業務功能中導出是必不可少的功能&#xff0c;接下來為大家演示在導出xlsx的時候的操作 效果圖 1、安裝 npm install xlsx -S npm inst…

Discuz!X3.4論壇網站公安備案號怎樣放到網站底部?

Discuz&#xff01;網站的工信部備案號都知道在后臺——全局——站點信息——網站備案信息代碼填寫&#xff0c;那公安備案號要添加在哪里呢&#xff1f;并沒有看到公安備案號填寫欄&#xff0c;今天馳網飛飛和你分享 1&#xff09;工信部備案號和公安備案號統一填寫到網站備案…

數據預處理

數據預處理 引入一.配置java , hadoop , maven的window本機環境變量1.配置2.測試是否配置成功 二.創建一個Maven項目三.導入hadoop依賴四.數據清洗1.數據清洗的java代碼2.查看數據清洗后的輸出結果 引入 做數據預處理 需要具備的條件 : java,hadoop,maven環境以及idea軟件 一…

斯坦福2024人工智能指數報告 2

《人工智能指數報告》由斯坦福大學、AI指數指導委員會及業內眾多大佬Raymond Perrault、Erik Brynjolfsson 、James Manyika、Jack Clark等人員和組織合著&#xff0c;旨在追蹤、整理、提煉并可視化與人工智能&#xff08;AI&#xff09;相關各類數據&#xff0c;該報告已被大多…

靜態網站部署指南

一、資源準備 1.1 服務器 # 當前的服務器,公網ip:127.0.0.1 # 通過ssh協議連接訪問服務器1.2 域名 目前個人擁有的域名有: 域名所有者有效期wujinet.top個人2029-04-151.3 網站代碼 純靜態網站,網站源碼由筆者自行開發并提供發布部署的技術支持。 二、技術棧 2.0 源碼…

linux部署rustdesk

1.拉取RustDesk鏡像 sudo docker image pull rustdesk/rustdesk-server2.啟動hbbs服務 sudo docker run --name hbbs -p 21115:21115 -p 21116:21116 -p 21116:21116/udp -p 21118:21118 -v pwd:/root -td --nethost rustdesk/rustdesk-server hbbs3.啟動hbbr服務 sudo dock…

spring boot 之 結合aop整合日志

AOP 該切面僅用于請求日志記錄&#xff0c;若有其他需求&#xff0c;在此基礎上擴展即可&#xff0c;不多逼逼&#xff0c;直接上代碼。 引入切面依賴 <!-- 切面 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>sp…

【C++】set與map

目錄 一、鍵值對 二、set 1. set的模板參數列表 2. set的構造 3. set的迭代器 4. set的容量 5. set的修改 6. set的查找 三、map 1. map的模板參數列表 2. map的構造 3. map的迭代器 4. map的容量 5. map的修改 6. map的查找 一、鍵值對 用來表示具有一一對應關…

SARscape5.7已經支持3米陸探一號(LT-1)數據處理

SARsacpe5.6.2.1版本已經開始支持LT-1的數據處理&#xff0c;由于當時只獲取了12米的條帶模式2&#xff08;STRIP2&#xff09;例子數據&#xff0c;對3米條帶模式1&#xff08;STRIP1&#xff09;數據的InSAR處理軌道誤差挺大&#xff0c;可能會造成干涉圖異常。 SARsacpe5.7最…

三十篇:動脈脈搏:企業業務處理系統的生命力

動脈脈搏&#xff1a;企業業務處理系統的生命力 1. 引言 在數字經濟的浪潮下&#xff0c;企業之間的競爭已不僅僅是產品和服務的競爭&#xff0c;更是信息處理能力的競爭。業務處理系統&#xff08;Transaction Processing System, TPS&#xff09;是企業信息系統架構的基礎&a…

Python3 筆記:Python之禪

打開Python Shell&#xff0c;輸入import this&#xff0c;按回車鍵運行程序。 Beautiful is better than ugly. 優雅勝于丑陋。 Explicit is better than implicit. 明確勝于含糊。 Simple is better than complex. 簡單勝于復雜。

圖形學初識--紋理采樣和Wrap方式

文章目錄 前言正文1、為什么需要紋理采樣&#xff1f;2、什么是紋理采樣&#xff1f;3、如何進行紋理采樣&#xff1f;&#xff08;1&#xff09;假設繪制區域為矩形&#xff08;2&#xff09;假設繪制區域為三角形 4、什么是紋理的Wrap方式&#xff1f;5、有哪些紋理的Wrap方式…

洪師傅代駕系統開發 支持公眾號H5小程序APP 后端Java源碼

代駕流程圖 業務流程圖 管理端設置 1、首頁裝修 2、師傅獎勵配置 師傅注冊后,可享受后臺設置的新師傅可得的額外獎勵; 例:A注冊了師傅,新人獎勵可享受3天,第一天的第一筆訂單完成后可得正常傭金傭金*獎勵比例 完成第二筆/第三筆后依次可得正常傭金傭金*獎勵比例 完成的第四…