瑞芯微RV1126——人臉識別源碼分析

本節內容主要分為3部分,第一部分是流程結構圖;第二部分為人臉識別代碼流程;第三部分為具體的代碼分析。

1.流程結構圖

2.人臉識別代碼流程

1、人臉數據的初始化:

init_all_rockx_face_data();init_face_data();

2、創建rtsp會話,這里包括發送碼流數據,得客戶端,也就是我們在windows上用ffplay去拉流得時候,才會發送碼流數據給客戶端:

create_rtsp_demo(554);
rtsp_new_session
rtsp_set_video
rtsp_sync_video_ts

**
3、初始化vi通道屬性**

 VI_CHN_ATTR_S vi_chn_attr;

4、初始化視頻處理屬性

RGA_ATTR_S stRgaAttr;

5、初始化編碼通道屬性:

VENC_CHN_ATTR_S venc_chn_attr;

6、綁定數據源:

RK_MPI_SYS_Bind

7、開始捕獲碼流:

RK_MPI_VI_StartStream

8、執行三個對應的線程:

  • pthread_create(&rockx_pid, NULL, rockx_vi_detect_thread, NULL);
  • pthread_create(&venc_pid, NULL, rockx_vi_face_recognize_venc_thread, NULL);
  • pthread_create(&rtsp_pid, NULL, rockx_venc_rtsp_thread, NULL);

**9、銷毀申請的系統資源; **

3.核心代碼分析

初始化vi通道屬性;初始化視頻處理屬性;初始化編碼通道屬性;綁定數據源;開始捕獲碼流:

//初始化vi通道屬性VI_CHN_ATTR_S vi_chn_attr;vi_chn_attr.pcVideoNode = pDeviceName;vi_chn_attr.u32BufCnt = u32BufCnt;vi_chn_attr.u32Width = u32Width;vi_chn_attr.u32Height = u32Height;//你的攝像頭分辨率大小不要超過vencvi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr);//設置vi通道屬性ret |= RK_MPI_VI_EnableChn(s32CamId, 0);//使能vi通道屬性,讓其生效if (ret){printf("ERROR: create rkisp0 VI[0] error! ret=%d\n", ret);return 0;}//初始化rga屬性RGA_ATTR_S stRgaAttr;stRgaAttr.bEnBufPool = RK_TRUE;stRgaAttr.u16BufPoolCnt = 2;stRgaAttr.u16Rotaion = 0;stRgaAttr.stImgIn.u32X = 0;stRgaAttr.stImgIn.u32Y = 0;stRgaAttr.stImgIn.imgType = IMAGE_TYPE_NV12;stRgaAttr.stImgIn.u32Width = u32Width;stRgaAttr.stImgIn.u32Height = u32Height;stRgaAttr.stImgIn.u32HorStride = u32Width;stRgaAttr.stImgIn.u32VirStride = u32Height;stRgaAttr.stImgOut.u32X = 0;stRgaAttr.stImgOut.u32Y = 0;stRgaAttr.stImgOut.imgType = IMAGE_TYPE_NV12;stRgaAttr.stImgOut.u32Width = disp_width;stRgaAttr.stImgOut.u32Height = disp_height;stRgaAttr.stImgOut.u32HorStride = disp_width;stRgaAttr.stImgOut.u32VirStride = disp_height;ret = RK_MPI_RGA_CreateChn(0, &stRgaAttr);//rga通道if (ret){printf("ERROR: Create rga[0] falied! ret=%d\n", ret);return -1;}//初始化編碼屬性VENC_CHN_ATTR_S venc_chn_attr;memset(&venc_chn_attr, 0, sizeof(VENC_CHN_ATTR_S));venc_chn_attr.stVencAttr.u32PicWidth = disp_width;venc_chn_attr.stVencAttr.u32PicHeight = disp_height;venc_chn_attr.stVencAttr.u32VirWidth = disp_width;venc_chn_attr.stVencAttr.u32VirHeight = disp_height;venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;venc_chn_attr.stVencAttr.u32Profile = 66;venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;//恒定的編碼碼率類型venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = disp_width * disp_height * 3;venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);//創建編碼通道if (ret){printf("ERROR: Create venc failed!\n");exit(0);}//初始化mpp通道MPP_CHN_S vi_chn;MPP_CHN_S rga_chn;vi_chn.enModId = RK_ID_VI;vi_chn.s32ChnId = 0;rga_chn.enModId = RK_ID_RGA;rga_chn.s32ChnId = 0;ret = RK_MPI_SYS_Bind(&vi_chn, &rga_chn);//綁定vi和rga通道if (ret != 0){printf("[VI] vi id: %d bind venc id: %d, ret: %d error\n", vi_chn.s32ChnId, rga_chn.s32ChnId, ret);return -1;}

初始化三個線程

  //初始化三個線程idpthread_t rockx_pid;pthread_t venc_pid;pthread_t rtsp_pid;//創建人臉檢測線程pthread_create(&rockx_pid, NULL, rockx_vi_detect_thread, NULL);//人臉識別線程pthread_create(&venc_pid, NULL, rockx_vi_face_recognize_venc_thread, NULL);//人臉編碼rtsp傳輸線程pthread_create(&rtsp_pid, NULL, rockx_venc_rtsp_thread, NULL);

人臉檢測線程

void *rockx_vi_detect_thread(void *args)
{//自動釋放線程資源pthread_detach(pthread_self());//創建一個類對象thread_mapS_THREAD_MAP thread_map;//對thread_map進行初始化get_thread_map(0, &thread_map);//定義了一個map類型database_face_map對象map<string, rockx_face_feature_t> database_face_map = thread_map.thread_map;//定義迭代器database_itermap<string, rockx_face_feature_t>::iterator database_iter;//定義一個緩沖區MEDIA_BUFFER src_mb = NULL;//人臉模式枚舉變量定義rockx_module_t data_version;data_version = ROCKX_MODULE_FACE_DETECTION_V2;//定義一個人臉執行返回結果變量rockx_ret_t rockx_ret;//定義人臉檢測處理指針變量rockx_handle_t face_det_handle;//定義人臉識別特征提取處理指針變量rockx_handle_t face_recognize_handle;//定義人臉特征點定位處理指針變量rockx_handle_t face_5landmarks_handle;//定義了人臉標記檢測處理指針變量rockx_handle_t face_masks_det_handle;//定義人臉配置結構體指針變量rockx_config_t *config = rockx_create_config();//獲取人臉配置值//添加配置人臉模型存放路徑,這里是存放在共享目錄下:/mnt/nfs/rockx_data/rockx_add_config(config, ROCKX_CONFIG_DATA_PATH, "/mnt/nfs/rockx_data/");//創建使用人臉模型數據,來處理人臉檢測rockx_ret = rockx_create(&face_det_handle, data_version, config,sizeof(rockx_config_t));//判斷是否創建使用人臉模型數據 來處理人臉檢測是否成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init face_detect error %d\n", rockx_ret);return NULL;}//使用人臉模型數據來人臉識別特征提取rockx_ret = rockx_create(&face_recognize_handle, ROCKX_MODULE_FACE_RECOGNIZE,config, sizeof(rockx_config_t));//識別是否成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init face_recognize error %d\n", rockx_ret);return NULL;}//使用模型算法數據來做人臉特征點定位處理rockx_ret = rockx_create(&face_5landmarks_handle,ROCKX_MODULE_FACE_LANDMARK_5, config, 0);//判斷是否處理成功                         if (rockx_ret != ROCKX_RET_SUCCESS){printf("init rockx module ROCKX_MODULE_FACE_LANDMARK_68 error %d\n",rockx_ret);}// rockx_handle_t face_masks_det_handle;進行標記處理rockx_ret = rockx_create(&face_masks_det_handle,ROCKX_MODULE_FACE_MASKS_DETECTION, config, 0);if (rockx_ret != ROCKX_RET_SUCCESS){printf("init rockx module ROCKX_MODULE_FACE_MASKS_DETECTION error %d\n",rockx_ret);}//定義人臉圖片結構體變量,并進行成員賦值rockx_image_t input_image;input_image.width = 1920;input_image.height = 1080;input_image.pixel_format = ROCKX_PIXEL_FORMAT_YUV420SP_NV12;bool is_recognize = false;string predict = "";//rockx_face_result_t face_result;int ret;//做輪詢操作while (!quit){
#if 1//從指定通道中獲取數據緩沖區src_mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, 0, -1);if (!src_mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//從指定的MEDIA_BUFFER中獲取緩沖區數據大小input_image.size = RK_MPI_MB_GetSize(src_mb);input_image.data = (unsigned char *)RK_MPI_MB_GetPtr(src_mb);//從指定的MEDIA_BUFFER中獲取緩沖區數據指針
#endif#if 1//rockx_face_result_group_t face_result_group;//memset(&face_result_group, 0, sizeof(face_result_group));//定義人臉處理結果結構體變量rockx_object_array_t face_array;memset(&face_array, 0, sizeof(face_array));//開始人臉檢測rockx_ret = rockx_face_detect(face_det_handle, &input_image, &face_array, NULL);if (rockx_ret != ROCKX_RET_SUCCESS){printf("rockx_face_detect ERROR %d\n", rockx_ret);}//進行互斥處理set_rockx_face_array(face_array);//判斷檢測人臉特征數量值是否大于0if (face_array.count > 0){//rockx_queue->putRockxFaceArray(face_array);printf("face_count : %d\n", face_array.count);for (int i = 0; i < face_array.count; i++){if (1){int is_false_face;//進行人臉過濾處理ret = rockx_face_filter(face_5landmarks_handle, &input_image,&face_array.object[i].box, &is_false_face);if (ret != ROCKX_RET_SUCCESS){printf("rockx_face_filter error %d\n", ret);}if (is_false_face)continue;}
#if 1//人臉檢測結果(包括人臉、車牌、頭部、物體等)變量定義rockx_object_t max_face;rockx_object_t cur_face = face_array.object[i];//進行人臉區域計算處理操作int cur_face_box_area = (cur_face.box.right - cur_face.box.left) *(cur_face.box.bottom - cur_face.box.top);int max_face_box_area = (max_face.box.right - max_face.box.left) *(max_face.box.bottom - max_face.box.top);if (cur_face_box_area > max_face_box_area){max_face = cur_face;}//檢測輸出處理rockx_image_t out_img;memset(&out_img, 0, sizeof(rockx_image_t));//進行面部矯正對齊ret = rockx_face_align(face_5landmarks_handle, &input_image,&(max_face.box), NULL, &out_img);if (ret != ROCKX_RET_SUCCESS){printf("face_align failed\n");}//人臉特征結果變量定義rockx_face_feature_t out_feature;//獲取人臉特征rockx_face_recognize(face_recognize_handle, &out_img, &out_feature);for (database_iter = database_face_map.begin();database_iter != database_face_map.end(); database_iter++){float similarity;//比較兩個人臉特征的相似性ret = rockx_face_feature_similarity(&database_iter->second,&out_feature, &similarity);printf("simple_value = %lf\n", similarity);//判斷預測精度if (similarity <= 1.0){is_recognize = true;//predict_name_bak = database_iter->first;predict = database_iter->first;break;}else{is_recognize = false;predict = "";continue;}}if (is_recognize == true){predict = database_iter->first;}else{predict = "";}set_rockx_prdict_name(predict);#endif}}
#endif//釋放緩沖區RK_MPI_MB_ReleaseBuffer(src_mb);src_mb = NULL;}//釋放相關人臉處理數據模塊rockx_destroy(face_det_handle);rockx_destroy(face_recognize_handle);rockx_destroy(face_5landmarks_handle);return NULL;
}

人臉識別線程

void *rockx_vi_face_recognize_venc_thread(void *args)
{pthread_detach(pthread_self());//線程資源自動釋放MEDIA_BUFFER mb = NULL; //媒體緩存區int ret;float x_rate = (float)1280 / 1920;float y_rate = (float)720 / 1080;while (!quit){//從指定通道中獲取數據緩沖區mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, 0, -1);if (!mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//獲取人臉處理結果rockx_object_array_t face_array = get_rockx_face_array();//創建mat對象,并創建了720x1080的像素塊,每個像素每個通道的位數都是8位,一個字節的。上述CV_8UC3中的8表示8位、UC表示uchar類型、1表示1個通道Mat tmp_img = Mat(720, 1280, CV_8UC1, RK_MPI_MB_GetPtr(mb));
#if 1//對人臉x,y,w,h進行處理for (int i = 0; i < face_array.count; i++){int x = face_array.object[i].box.left * x_rate;int y = face_array.object[i].box.top * y_rate;int w = (face_array.object[i].box.right - face_array.object[i].box.left) * x_rate;int h = (face_array.object[i].box.bottom - face_array.object[i].box.top) * y_rate;if (x < 0)x = 0;if (y < 0)y = 0;while ((uint32_t)(x + w) >= 1280){w -= 16;}while ((uint32_t)(y + h) >= 720){h -= 16;}//獲取人臉預測名字string predict_name = get_rockx_prdict_name();printf("predict_name = %s\n", predict_name.c_str());nv12_border((char *)RK_MPI_MB_GetPtr(mb), 1280, 720, x, y, w, h, 255, 0, 255);int baseline;//計算人臉名字文本大小Size text_size = getTextSize(predict_name, 2, 2, 2, &baseline);Point origin;origin.x = tmp_img.cols / 4 - text_size.width / 4;origin.y = tmp_img.rows / 4 + text_size.height / 4;//把名字字符填充到文本框里面去cv::putText(tmp_img, predict_name, origin, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 0, 255), 3);}
#endif//釋放對應的資源RK_MPI_SYS_SendMediaBuffer(RK_ID_VENC, 0, mb);RK_MPI_MB_ReleaseBuffer(mb);mb = NULL;}return NULL;
}

人臉編碼rtsp傳輸線程

void *rockx_venc_rtsp_thread(void *args)
{pthread_detach(pthread_self());MEDIA_BUFFER mb = NULL;while (!quit){mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 0, -1);if (!mb){printf("ERROR: RK_MPI_SYS_GetMediaBuffer get null buffer!\n");break;}//rtsp來傳輸碼流rtsp_tx_video(g_rtsp_session, (unsigned char *)RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), RK_MPI_MB_GetTimestamp(mb));RK_MPI_MB_ReleaseBuffer(mb);rtsp_do_event(g_rtsplive);}return NULL;
}

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

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

相關文章

一個典型的分布式緩存系統是什么樣的?no.32

分布式 Redis 服務 由于本課程聚焦于緩存&#xff0c;接下來&#xff0c;我將以微博內的 分布式 Redis 服務系統為例&#xff0c;介紹一個典型的分布式緩存系統的組成。 微博的 Redis 服務內部也稱為 RedisService。RedisService 的整體架構如圖所示。主要分為Proxy、存儲、集…

產品推薦 | 基于Xilinx XCKU115的半高PCIe x8 硬件加速卡

一、板卡概述 本板卡系我公司自主研發&#xff0c;采用Xilinx公司的XCKU115-3-FLVF1924-E芯片作為主處理器&#xff0c;主要用于FPGA硬件加速。板卡設計滿足工業級要求。如下圖所示&#xff1a; 二、功能和技術指標 板卡功能 參數內容 主處理器 XCKU115-3-FLVF1924-E 板卡…

UE4/UE5像素流送云推流:多人訪問不穩定、畫面糊、端口占用多等

UE4/UE5想要實現網頁訪問&#xff0c;很多工程師會選擇guan方的像素流送。但這個技術要求在模型開發初期就接入。對于一些已有UE模型是無法進行流化的。雖然也可以解決新UE模型的網頁訪問問題&#xff0c;但在實際的應用中&#xff0c;點量云流也收到很多反饋說&#xff0c;使用…

netty-socketio 集群隨記

實現netty-socketio集群的方式 代碼實例 PostConstructpublic void subscribe() {pubSubStore.subscribe(PubSubType.DISPATCH, new PubSubListener<DispatchMessage>() {Overridepublic void onMessage(DispatchMessage message) {log.debug("subscribe: {}"…

Python爬取B站視頻:封裝一下

&#x1f4da;博客主頁&#xff1a;knighthood2001 ?公眾號&#xff1a;認知up吧 &#xff08;目前正在帶領大家一起提升認知&#xff0c;感興趣可以來圍觀一下&#xff09; &#x1f383;知識星球&#xff1a;【認知up吧|成長|副業】介紹 ??如遇文章付費&#xff0c;可先看…

大數據Hadoop之-工具HIVE(一)

大數據Hadoop之——數據倉庫Hive HIVE介紹Hive是基于Hadoop的一個數據倉庫(Data Aarehouse,簡稱數倉、DW),可以將結構化的數據文件映射為一張數據庫表,并提供類SQL查詢功能。是用于存儲、分析、報告的數據系統。 在Hadoop生態系統中,HDFS用于存儲數據,Yarn用于資源管理…

解釋Spring Bean的生命周期

Spring Bean的生命周期涉及到Bean的創建、配置、使用和銷毀的各個階段。理解這個生命周期對于編寫高效的Spring應用和充分利用框架的功能非常重要。下面是Spring Bean生命周期的主要步驟&#xff1a; 1. 實例化Bean Spring容器首先將使用Bean的定義&#xff08;無論是XML、注…

使用Golang調用騰訊云郵件模版發送郵件

文章目錄 一、騰訊云郵件模版創建1.1 發信域名配置1.2 發信地址設置1.3 發信模版設置 二、通過Golang發送郵件2.1 代碼示例2.2 代碼說明 三、常見問題3.1 UnsupportedRegion3.2 InvalidTemplateID 本文檔介紹了如何使用Golang編寫代碼&#xff0c;通過騰訊云郵件服務&#xff0…

【Linux】中的常見的重要指令(中)

目錄 一、man指令 二、cp指令 三、cat指令 四、mv指令 五、more指令 六、less指令 七、head指令 八、tail指令 一、man指令 Linux的命令有很多參數&#xff0c;我們不可能全記住&#xff0c;我們可以通過查看聯機手冊獲取幫助。訪問Linux手冊頁的命令是 man 語法: m…

白嫖免費圖床!CloudFlare R2太香了!

1 為啥要折騰搭建一個專屬圖床&#xff1f; 技術大佬寫博客都用 md 格式&#xff0c;要在多平臺發布&#xff0c;圖片就得有外鏈后續如博客遷移&#xff0c;國內博客網站如掘金&#xff0c;簡書&#xff0c;語雀等都做了防盜鏈&#xff0c;圖片無法遷移 2 為啥選擇CloudFlare…

對話太醫管家CEO徐晶:數字化技術正在為健康管理行業帶來新平衡丨數字思考者50人...

ITValue 鈦媒體特別專題策劃《數字思考者50人》&#xff1a;探訪中國深刻的數字化思考者群體。我們理解的“TechThinker”&#xff0c;涵蓋了中國數字化浪潮中的技術踐行者、政策制定者與投資決策者。在這場長達10年的乘風破浪中&#xff0c;每個人都在分享技術進步的果實&…

leetcode445-Add Two Numbers II

題目 給你兩個 非空 鏈表來代表兩個非負整數。數字最高位位于鏈表開始位置。它們的每個節點只存儲一位數字。將這兩數相加會返回一個新的鏈表。 你可以假設除了數字 0 之外&#xff0c;這兩個數字都不會以零開頭。 示例1&#xff1a; 輸入&#xff1a;l1 [7,2,4,3], l2 [5,6…

文件系統--軟硬鏈接

文章目錄 現象軟鏈接硬鏈接 現象 建立軟鏈接 建立硬鏈接 // 刪除軟硬鏈接都可以用 unlink 指令 unlink soft-link軟鏈接 軟鏈接是一個獨立的文件&#xff0c;因為有獨立的inode number 軟鏈接的內容&#xff1a;目標文件所對應的路勁字符串如果我們直接查看軟鏈接文件&#…

vue2vue3為什么el-table樹狀表格失效?

上圖所示&#xff0c;后端返回字段中有hasChildren字段。 解決樹狀表格失效方案&#xff1a; 從后端拿到數據后&#xff0c;遞歸去掉該字段&#xff0c;然后就能正常顯示。&#xff08;復制下方代碼&#xff0c;直接用&#xff09; 親測有效&#xff0c;vue2、vue3通用 /**…

如何運用多媒體,打造企業實力展示廳?

企業文化、產品是其長期發展的根本所在&#xff0c;為此越來越多的企業開始選擇運用多媒體互動&#xff0c;來打造企業多媒體展廳的方式&#xff0c;對企業文化、品牌形象、產品進行推廣宣傳&#xff0c;并在多媒體互動裝置的支持下&#xff0c;能讓客戶能夠快速且全面的了解企…

基于SSM的“酒店管理系統”的設計與實現(源碼+數據庫+文檔)

基于SSM的“酒店管理系統”的設計與實現&#xff08;源碼數據庫文檔) 開發語言&#xff1a;Java 數據庫&#xff1a;MySQL 技術&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系統展示 首頁 管理員登錄頁面 用戶管理頁面 客房信息查詢 酒店詳細信息 后臺…

MySQL入門學習.數據庫組成.存儲引擎

存儲引擎是 MySQL 數據庫的一個重要組成部分&#xff0c;它決定了數據的存儲方式、索引方式、事務支持等特性。MySQL 支持多種存儲引擎&#xff0c;常見的有 InnoDB、MyISAM、Memory 等。 存儲引擎的特點和使用方法&#xff1a; 1. InnoDB&#xff1a; 是 MySQL 默認的存儲引…

APP廣告變現怎么實現的,背后邏輯是什么?

廣告變現的實現主要基于以下幾個關鍵步驟和邏輯&#xff1a; 用戶獲取與留存&#xff1a;首先&#xff0c;APP需要吸引足夠的用戶并確保他們的留存率。只有擁有龐大且活躍的用戶基礎&#xff0c;APP才能吸引廣告商投放廣告。因此&#xff0c;開發者需要通過優化APP質量、提升用…

數字人實訓室解決方案

前言 近年來&#xff0c;政策層面的積極推動為數字人產業鋪設了堅實的基石。2021年&#xff0c;“十四五”規劃將虛擬數字技術納入其中&#xff0c;強調技術創新引領行業應用的革新&#xff0c;加速數字人在各領域的實際應用。緊接著的《“十四五”數字經濟發展規劃》進一步明確…

react封裝Spin重復使用loading效果antd

1. 代碼封裝 import React, { useState } from react; import { Spin } from antd; import ./index.scss;// 自定義Hook useLoadings export const useLoadings () > {// 存儲loading的狀態&#xff0c;key是loading的唯一標識&#xff0c;value是loading的顯示狀態 co…