NNTK_NLY

  • 2024-05-29
  • 回复了主题帖: 【AI挑战营第二站】算法工程化部署打包成SDK

    #AI挑战营第二站#RV1106的rknn模型转换、仿真推理

  • 发表了主题帖: #AI挑战营第二站#RV1106的rknn模型转换、仿真推理

    本帖最后由 NNTK_NLY 于 2024-5-29 20:41 编辑 1.环境搭建不再赘述,参考https://bbs.eeworld.com.cn/thread-1280038-1-1.html   2.模型转换 rknn = RKNN(verbose=True) #Pre-process config print('--> Config model') rknn.config(mean_values=[[28]], std_values=[[28]],target_platform='rv1106') print('done') # Load model print('--> Loading model') ret = rknn.load_onnx(model='mnist.onnx') if ret != 0: print('Load model failed!') exit(ret) print('done') # Build model print('--> Building model') ret = rknn.build(do_quantization=True, dataset='./data.txt',rknn_batch_size=1) if ret != 0: print('Build model failed!') exit(ret) print('done') # Export rknn model print('--> Export rknn model') ret = rknn.export_rknn('mnist.rknn') if ret != 0: print('Export rknn model failed!') exit(ret) print('done') # Release rknn.release()   3.紧接着进行模型仿真推理 # Set inputs img = cv2.imread('8.png') img = cv2.resize(img, (28, 28)) #cv2.imwrite('2r.jpg', img) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = np.expand_dims(img, 0) img = np.expand_dims(img, 3) # Init runtime environment print('--> Init runtime environment') ret = rknn.init_runtime() if ret != 0: print('Init runtime environment failed!') exit(ret) print('done') # Inference print('--> Running model') outputs = rknn.inference(inputs=[img]) #Post Process print('--> PostProcess') with open('./synset.txt', 'r') as f: labels = [l.rstrip() for l in f] scores = softmax(outputs[0]) # print the top-5 inferences class scores = np.squeeze(scores) a = np.argsort(scores)[::-1] print('-----TOP 5-----') for i in a[0:5]: print('[%d] score=%.2f class="%s"' % (i, scores[i], labels[i])) print('done') # Release rknn.release() 注意:如需仿真推理,第二步2.模型转换中先不释放rknn实体 # Release rknn.release()   4.模型转换log I rknn-toolkit2 version: 2.0.0b0+9bab5682 --> Config model done --> Loading model I It is recommended onnx opset 19, but your onnx model opset is 10! I Model converted from pytorch, 'opset_version' should be set 19 in torch.onnx.export for successful convert! I Loading : 100%|██████████████████████████████████████████████████| 9/9 [00:00<00:00, 16897.38it/s] done --> Building model D base_optimize ... D base_optimize done. D D fold_constant ... D fold_constant done. D D correct_ops ... D correct_ops done. D D fuse_ops ... D fuse_ops results: D replace_reshape_gemm_by_conv: remove node = ['/Reshape', '/fc1/Gemm'], add node = ['/fc1/Gemm_2conv', '/fc1/Gemm_2conv_reshape'] D swap_reshape_relu: remove node = ['/fc1/Gemm_2conv_reshape', '/Relu_2'], add node = ['/Relu_2', '/fc1/Gemm_2conv_reshape'] D convert_gemm_by_conv: remove node = ['/fc2/Gemm'], add node = ['/fc2/Gemm_2conv_reshape1', '/fc2/Gemm_2conv', '/fc2/Gemm_2conv_reshape2'] D fuse_two_reshape: remove node = ['/fc1/Gemm_2conv_reshape'] D remove_invalid_reshape: remove node = ['/fc2/Gemm_2conv_reshape1'] D fold_constant ... D fold_constant done. D fuse_ops done. D D sparse_weight ... D sparse_weight done. D I GraphPreparing : 100%|██████████████████████████████████████████| 10/10 [00:00<00:00, 4456.81it/s] I Quantizating : 100%|████████████████████████████████████████████| 10/10 [00:00<00:00, 1337.34it/s] D D quant_optimizer ... D quant_optimizer results: D adjust_relu: ['/Relu_2', '/Relu_1', '/Relu'] D quant_optimizer done. D W build: The default input dtype of 'input' is changed from 'float32' to 'int8' in rknn model for performance! Please take care of this change when deploy rknn model with Runtime API! W build: The default output dtype of 'output' is changed from 'float32' to 'int8' in rknn model for performance! Please take care of this change when deploy rknn model with Runtime API! I rknn building ... I RKNN: [18:11:22.305] compress = 0, conv_eltwise_activation_fuse = 1, global_fuse = 1, multi-core-model-mode = 7, output_optimize = 1, layout_match = 1, enable_argb_group = 0 I RKNN: librknnc version: 2.0.0b0 (35a6907d79@2024-03-24T02:34:11) D RKNN: [18:11:22.308] RKNN is invoked D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNExtractCustomOpAttrs D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNExtractCustomOpAttrs D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNSetOpTargetPass D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNSetOpTargetPass D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNBindNorm D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNBindNorm D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNAddFirstConv D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNAddFirstConv D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNEliminateQATDataConvert D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNEliminateQATDataConvert D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNTileGroupConv D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNTileGroupConv D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNTileFcBatchFuse D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNTileFcBatchFuse D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNAddConvBias D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNAddConvBias D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNTileChannel D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNTileChannel D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNPerChannelPrep D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNPerChannelPrep D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNBnQuant D RKNN: [18:11:22.318] <<<<<<<< end: rknn::RKNNBnQuant D RKNN: [18:11:22.318] >>>>>> start: rknn::RKNNFuseOptimizerPass D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNFuseOptimizerPass D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNTurnAutoPad D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNTurnAutoPad D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNInitRNNConst D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNInitRNNConst D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNInitCastConst D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNInitCastConst D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNMultiSurfacePass D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNMultiSurfacePass D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNReplaceConstantTensorPass D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNReplaceConstantTensorPass D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNSubgraphManager D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNSubgraphManager D RKNN: [18:11:22.319] >>>>>> start: OpEmit D RKNN: [18:11:22.319] <<<<<<<< end: OpEmit D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNLayoutMatchPass I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[/Relu_output_0] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[/pool/MaxPool_output_0] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[/Relu_1_output_0] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[/pool_1/MaxPool_output_0] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[/fc1/Gemm_output_0_new] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(64), tname:[output_conv] I RKNN: [18:11:22.319] AppointLayout: t->setNativeLayout(0), tname:[output] D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNLayoutMatchPass D RKNN: [18:11:22.319] >>>>>> start: rknn::RKNNAddSecondaryNode D RKNN: [18:11:22.319] <<<<<<<< end: rknn::RKNNAddSecondaryNode D RKNN: [18:11:22.319] >>>>>> start: OpEmit D RKNN: [18:11:22.319] finish initComputeZoneMap D RKNN: [18:11:22.320] <<<<<<<< end: OpEmit D RKNN: [18:11:22.320] >>>>>> start: rknn::RKNNSubGraphMemoryPlanPass D RKNN: [18:11:22.320] <<<<<<<< end: rknn::RKNNSubGraphMemoryPlanPass D RKNN: [18:11:22.320] >>>>>> start: rknn::RKNNProfileAnalysisPass D RKNN: [18:11:22.320] node: Reshape:/fc2/Gemm_2conv_reshape2, Target: NPU D RKNN: [18:11:22.320] <<<<<<<< end: rknn::RKNNProfileAnalysisPass D RKNN: [18:11:22.320] >>>>>> start: rknn::RKNNOperatorIdGenPass D RKNN: [18:11:22.320] <<<<<<<< end: rknn::RKNNOperatorIdGenPass D RKNN: [18:11:22.320] >>>>>> start: rknn::RKNNWeightTransposePass W RKNN: [18:11:22.331] Warning: Tensor /fc2/Gemm_2conv_reshape2_shape need paramter qtype, type is set to float16 by default! W RKNN: [18:11:22.331] Warning: Tensor /fc2/Gemm_2conv_reshape2_shape need paramter qtype, type is set to float16 by default! D RKNN: [18:11:22.331] <<<<<<<< end: rknn::RKNNWeightTransposePass D RKNN: [18:11:22.331] >>>>>> start: rknn::RKNNCPUWeightTransposePass D RKNN: [18:11:22.331] <<<<<<<< end: rknn::RKNNCPUWeightTransposePass D RKNN: [18:11:22.331] >>>>>> start: rknn::RKNNModelBuildPass D RKNN: [18:11:22.336] <<<<<<<< end: rknn::RKNNModelBuildPass D RKNN: [18:11:22.336] >>>>>> start: rknn::RKNNModelRegCmdbuildPass D RKNN: [18:11:22.336] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ D RKNN: [18:11:22.336] Network Layer Information Table D RKNN: [18:11:22.336] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ D RKNN: [18:11:22.336] ID OpType DataType Target InputShape OutputShape Cycles(DDR/NPU/Total) RW(KB) FullName D RKNN: [18:11:22.336] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ D RKNN: [18:11:22.336] 0 InputOperator INT8 CPU \ (1,1,28,28) 0/0/0 0 InputOperator:input D RKNN: [18:11:22.336] 1 ConvRelu INT8 NPU (1,1,28,28),(32,1,3,3),(32) (1,32,28,28) 4429/7056/7056 2 Conv:/conv1/Conv D RKNN: [18:11:22.336] 2 MaxPool INT8 NPU (1,32,28,28) (1,32,14,14) 5092/0/5092 24 MaxPool:/pool/MaxPool D RKNN: [18:11:22.336] 3 ConvRelu INT8 NPU (1,32,14,14),(64,32,3,3),(64) (1,64,14,14) 6131/7488/7488 24 Conv:/conv2/Conv D RKNN: [18:11:22.336] 4 MaxPool INT8 NPU (1,64,14,14) (1,64,7,7) 2546/0/2546 12 MaxPool:/pool_1/MaxPool D RKNN: [18:11:22.336] 5 ConvRelu INT8 NPU (1,64,7,7),(128,64,7,7),(128) (1,128,1,1) 65865/12544/65865 396 Conv:/fc1/Gemm_2conv D RKNN: [18:11:22.336] 6 Conv INT8 NPU (1,128,1,1),(10,128,1,1),(10) (1,10,1,1) 252/64/252 1 Conv:/fc2/Gemm_2conv D RKNN: [18:11:22.336] 7 Reshape INT8 NPU (1,10,1,1),(2) (1,10) 7/0/7 0 Reshape:/fc2/Gemm_2conv_reshape2 D RKNN: [18:11:22.336] 8 OutputOperator INT8 CPU (1,10) \ 0/0/0 0 OutputOperator:output D RKNN: [18:11:22.336] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ D RKNN: [18:11:22.337] <<<<<<<< end: rknn::RKNNModelRegCmdbuildPass D RKNN: [18:11:22.337] >>>>>> start: rknn::RKNNFlatcModelBuildPass D RKNN: [18:11:22.337] Export Mini RKNN model to /tmp/tmphfyahgcw/check.rknn D RKNN: [18:11:22.337] >>>>>> end: rknn::RKNNFlatcModelBuildPass D RKNN: [18:11:22.337] >>>>>> start: rknn::RKNNMemStatisticsPass D RKNN: [18:11:22.337] --------------------------------------------------------------------------------------------------------------------------------- D RKNN: [18:11:22.337] Feature Tensor Information Table D RKNN: [18:11:22.337] -----------------------------------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] ID User Tensor DataType DataFormat OrigShape NativeShape | [Start End) Size D RKNN: [18:11:22.337] -----------------------------------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] 1 ConvRelu input INT8 NC1HWC2 (1,1,28,28) (1,1,28,28,1) | 0x00069000 0x00069380 0x00000380 D RKNN: [18:11:22.337] 2 MaxPool /Relu_output_0 INT8 NC1HWC2 (1,32,28,28) (1,2,28,28,16) | 0x00069380 0x0006f580 0x00006200 D RKNN: [18:11:22.337] 3 ConvRelu /pool/MaxPool_output_0 INT8 NC1HWC2 (1,32,14,14) (1,2,14,14,16) | 0x0006f580 0x00070e00 0x00001880 D RKNN: [18:11:22.337] 4 MaxPool /Relu_1_output_0 INT8 NC1HWC2 (1,64,14,14) (1,4,14,14,16) | 0x00069000 0x0006c100 0x00003100 D RKNN: [18:11:22.337] 5 ConvRelu /pool_1/MaxPool_output_0 INT8 NC1HWC2 (1,64,7,7) (1,4,7,7,16) | 0x0006c100 0x0006ce00 0x00000d00 D RKNN: [18:11:22.337] 6 Conv /fc1/Gemm_output_0_new INT8 NC1HWC2 (1,128,1,1) (1,8,1,1,16) | 0x00069000 0x00069080 0x00000080 D RKNN: [18:11:22.337] 7 Reshape output_conv INT8 NC1HWC2 (1,10,1,1) (1,1,1,1,16) | 0x00069080 0x00069090 0x00000010 D RKNN: [18:11:22.337] 8 OutputOperator output INT8 UNDEFINED (1,10) (1,10) | 0x00069040 0x00069080 0x00000040 D RKNN: [18:11:22.337] -----------------------------------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] ----------------------------------------------------------------------------------------------------- D RKNN: [18:11:22.337] Const Tensor Information Table D RKNN: [18:11:22.337] -------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] ID User Tensor DataType OrigShape | [Start End) Size D RKNN: [18:11:22.337] -------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] 1 ConvRelu conv1.weight INT8 (32,1,3,3) | 0x00000000 0x00000480 0x00000480 D RKNN: [18:11:22.337] 1 ConvRelu conv1.bias INT32 (32) | 0x00000480 0x00000580 0x00000100 D RKNN: [18:11:22.337] 3 ConvRelu conv2.weight INT8 (64,32,3,3) | 0x00000580 0x00004d80 0x00004800 D RKNN: [18:11:22.337] 3 ConvRelu conv2.bias INT32 (64) | 0x00004d80 0x00004f80 0x00000200 D RKNN: [18:11:22.337] 5 ConvRelu fc1.weight INT8 (128,64,7,7) | 0x00004f80 0x00066f80 0x00062000 D RKNN: [18:11:22.337] 5 ConvRelu fc1.bias INT32 (128) | 0x00066f80 0x00067380 0x00000400 D RKNN: [18:11:22.337] 6 Conv fc2.weight INT8 (10,128,1,1) | 0x00067380 0x00067880 0x00000500 D RKNN: [18:11:22.337] 6 Conv fc2.bias INT32 (10) | 0x00067880 0x00067900 0x00000080 D RKNN: [18:11:22.337] 7 Reshape /fc2/Gemm_2conv_reshape2_shape INT64 (2) | 0x00067900*0x00067940 0x00000040 D RKNN: [18:11:22.337] -------------------------------------------------------------------+--------------------------------- D RKNN: [18:11:22.337] ---------------------------------------- D RKNN: [18:11:22.337] Total Internal Memory Size: 31.5KB D RKNN: [18:11:22.337] Total Weight Memory Size: 414.312KB D RKNN: [18:11:22.337] ---------------------------------------- D RKNN: [18:11:22.337] <<<<<<<< end: rknn::RKNNMemStatisticsPass I rknn buiding done. done --> Export rknn model done   5.仿真推理log --> Init runtime environment I Target is None, use simulator! done --> Running model W inference: The 'data_format' is not set, and its default value is 'nhwc'! I GraphPreparing : 100%|██████████████████████████████████████████| 12/12 [00:00<00:00, 4513.64it/s] I SessionPreparing : 100%|████████████████████████████████████████| 12/12 [00:00<00:00, 1368.27it/s] --> PostProcess -----TOP 5----- [8] score=1.00 class="8 8" [3] score=0.00 class="3 3" [9] score=0.00 class="9 9" [2] score=0.00 class="2 2" [6] score=0.00 class="6 6" done   6.模型转换工程目录下文件     7.data.txt内容 ./2.png   8.synset.txt内容 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9    9.仿真推理所用图片:     10.附github工程链接https://github.com/Ainit-NNTK/mnist_onnx_export_rknn.git            

  • 2024-05-28
  • 回复了主题帖: 【AI挑战营终点站】应用落地:部署手写数字识别应用到幸狐RV1106开发板

    先打卡一下,后续优化https://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1283213&page=1&extra=#pid3333154

  • 发表了主题帖: #AI挑战营终点站#RV1106手写数字识别,基于opencv-mobile和ncnn、rtsp部署

    本帖最后由 NNTK_NLY 于 2024-5-28 21:17 编辑 1.onnx模型转ncnn模型     https://convertmodel.com/ 2.下载opencv-mobile预编译包     https://github.com/nihui/opencv-mobile/releases/download/v26/opencv-mobile-4.9.0-luckfox-pico.zip 3.为luckfox-pico编译ncnn git clone https://github.com/Tencent/ncnn.git cd ./ncnn./toolchains vi luckfox-pico.cmake 填入 set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) if(DEFINED ENV{TOOLCHAIN_ROOT_PATH}) file(TO_CMAKE_PATH $ENV{TOOLCHAIN_ROOT_PATH} TOOLCHAIN_ROOT_PATH) else() message(FATAL_ERROR "TOOLCHAIN_ROOT_PATH env must be defined") endif() set(TOOLCHAIN_ROOT_PATH ${TOOLCHAIN_ROOT_PATH} CACHE STRING "root path to toolchain") set(CMAKE_C_COMPILER "/mnt/sdd1/soc/toolchains/luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc") set(CMAKE_CXX_COMPILER "/mnt/sdd1/soc/toolchains/luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon") set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon") # cache flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") 其中set(CMAKE_C_COMPILER "/mnt/sdd1/soc/toolchains/luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc") set(CMAKE_CXX_COMPILER "/mnt/sdd1/soc/toolchains/luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++") 按实际修改   回到ncnn根目录 mkdir -p build-luckfox-pico cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/luckfox-pico.cmake .. make -j4 make install   3.参考 git clone https://github.com/luckfox-eng29/luckfox_pico_rtsp_opencv cd ./luckfox_pico_rtsp_opencv cp ncnn/build-luckfox-pico/install/* ./ncnn_install 改CMakeLists.txt set(CMAKE_C_COMPILER "/path/to/luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc") set(CMAKE_CXX_COMPILER "/path/to//luckfox-pico/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++") 4.编写main.cpp opencv获取摄像头帧 void *data = RK_MPI_MB_Handle2VirAddr(stVpssFrame.stVFrame.pMbBlk); cv::Mat frame(height, width, CV_8UC3, data); opencv框选数字 cv::Rect digit_rect = find_digit_contour(frame); digit_rect.x = std::max(0, digit_rect.x - 10); digit_rect.y = std::max(0, digit_rect.y - 50); digit_rect.width = std::min(frame.cols - digit_rect.x, digit_rect.width + 20); digit_rect.height = std::min(frame.rows - digit_rect.y, digit_rect.height + 100);   cv::Rect find_digit_contour(const cv::Mat &image) { cv::Mat gray, blurred, edged; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 0); cv::Canny(blurred, edged, 50, 150); std::vector<std::vector<cv::Point>> contours; cv::findContours(edged, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); if (contours.empty()) { return cv::Rect(); } // 找到最大的轮廓 auto largest_contour = std::max_element(contours.begin(), contours.end(), [](const std::vector<cv::Point> &a, const std::vector<cv::Point> &b) { return cv::contourArea(a) < cv::contourArea(b); }); return cv::boundingRect(*largest_contour); } opencv截取数字的区域 cv::Mat digit_region = frame(digit_rect); opencv转灰度图并resize到28*28 cv::cvtColor(digit_region, gray_1ch, cv::COLOR_BGR2GRAY); threshold(gray_1ch, gray_1ch, atoi(argv[1]), 255, cv::THRESH_BINARY_INV); cv::resize(gray_1ch, frame_resize, cv::Size(28, 28), 0, 0, cv::INTER_AREA); ncnn推理 ncnn::Mat in = ncnn::Mat::from_pixels(frame_resize.data, ncnn::Mat::PIXEL_GRAY, frame_resize.cols, frame_resize.rows); // PIXEL_BGR2GRAY ncnn::Mat out; double total_latency = 0; ncnn::Extractor ex = net.create_extractor(); ex.input("flatten_input", in); ex.extract("dense_2", out); const float *ptr = out.channel(0); int gussed = -1; float guss_exp = -10000000; for (int i = 0; i < out.w * out.h; i++) { printf("%d: %.2f\n", i, ptr[i]); if (guss_exp < ptr[i]) { gussed = i; guss_exp = ptr[i]; } } printf("I think it is number %d!\n", gussed); 在图像上显示预测结果 cv::rectangle(frame, digit_rect, cv::Scalar(0, 255, 0), 2); sprintf(fps_text, "number:%d", gussed); cv::putText(frame, fps_text,cv::Point(40, 40), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2); 最后memcpy到rtsp帧中 memcpy(data, frame.data, width * height * 3); 编译 mkdir build cd build cmake .. make && make install 生成可执行文件在luckfox_pico_rtsp_opencv-ncnn-mnist文件夹中 ./luckfox_pico_rtsp_opencv-ncnn-mnist/luckfox_pico_rtsp_opencv-ncnn-mnist   5.识别效果               6.附工程开源链接 https://github.com/Ainit-NNTK/luckfox-pico-opencv-ncnn 7.总结     opencv-mobile + ncnn推理速度还行,不过截取数字时框选有误差导致识别出错     后续打算优化数字截取框算法和更换为rknn推理框架并对比推理效果   8.附实时推理视频 [localvideo]f22b1dbb88b44173f4999d4684209151[/localvideo]                    

  • 2024-05-09
  • 回复了主题帖: #AI挑战营第一站# 利用pytorch进行手写数字模型训练的训练和转换

    测试模型 def test(model, device, test_loader): model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss pred = output.argmax(dim=1, keepdim=True) # get the index of the max log-probability correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format( test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) 训练模型测试结果:  

  • 回复了主题帖: 入围名单公布:嵌入式工程师AI挑战营(初阶),获RV1106 Linux 板+摄像头的名单

    个人信息已确认,领取板卡,可继续完成&分享挑战营第二站和第三站任务

  • 2024-04-14
  • 回复了主题帖: 免费申请:幸狐 RV1106 Linux 开发板(带摄像头),助力AI挑战营应用落地

    本帖最后由 NNTK_NLY 于 2024-4-14 19:08 编辑 #AI挑战营第一站# 利用pytorch进行手写数字模型训练的训练和转换 预期应用:使用摄像头获取手写图像,对图像进行处理然后进行NPU推理检测图片所写数字;完成摄像头车牌识别功能。

  • 回复了主题帖: 【AI挑战营第一站】模型训练:在PC上完成手写数字模型训练,免费申请RV1106开发板

    本帖最后由 NNTK_NLY 于 2024-4-14 19:10 编辑 模型训练的本质:使用训练数据集来训练构建模型,通过调整参数不断迭代优化模型,使模型训练出期望能力,能够对新数据进行预测或决策。 训练的最终结果:生成一个能够对输入新数据进行准确预测或决策的模型。 PyTorch是什么:一种神经网络学习框架,可用于训练深度学习模型 PyTorch目前都支持哪些系统和计算平台:支持系统:linux mac windows ,支持语言:python、C/C++,支持平台:CUDA、CPU #AI挑战营第一站# 利用pytorch进行手写数字模型训练的训练和转换

  • 发表了主题帖: #AI挑战营第一站# 利用pytorch进行手写数字模型训练的训练和转换

      安装pytorch https://pytorch.org/get-started/locally/ 加载程序库 import torch import os import numpy as np import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, random_split from torchvision import datasets, transforms 定义超参数 input_size = 1 * 28 * 28 num_classes = 10 num_epochs = 20 batch_size = 256 learning_rate = 0.0001 定义CNN模型 class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.layer1 = nn.Sequential( nn.Conv2d(1, 32, kernel_size=5, stride=1, padding=2), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2)) self.layer2 = nn.Sequential( nn.Conv2d(32, 64, kernel_size=5, stride=1, padding=2), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2)) self.drop_out = nn.Dropout() self.fc1 = nn.Linear(7 * 7 * 64, 1000) self.fc2 = nn.Linear(1000, num_classes) def forward(self, x): out = self.layer1(x) out = self.layer2(out) out = out.reshape(out.size(0), -1) out = self.drop_out(out) out = self.fc1(out) out = self.fc2(out) return out  训练模型 # 训练循环 for epoch in range(num_epochs): model.train() # 设置模型为训练模式 running_loss = 0.0 corrects = 0 for inputs, labels in train_loader: optimizer.zero_grad() # 清空之前的梯度 outputs = model(inputs) # 获取模型输出 loss = criterion(outputs, labels) # 计算损失 loss.backward() # 反向传播计算梯度 optimizer.step() # 使用优化器更新权重 _, preds = torch.max(outputs, 1) # 获取预测结果 corrects += torch.sum(preds == labels.data) # 计算正确预测的数量 running_loss += loss.item() # 累加损失 epoch_loss = running_loss / len(train_loader) epoch_acc = corrects.double() / train_total # 验证模型性能 model.eval() # 设置模型为评估模式 val_loss = 0.0 val_corrects = 0 with torch.no_grad(): # 不计算梯度 for inputs, labels in val_loader: outputs = model(inputs) loss = criterion(outputs, labels) val_loss += loss.item() _, preds = torch.max(outputs, 1) val_corrects += torch.sum(preds == labels.data) val_loss = val_loss / len(val_loader) val_acc = val_corrects.double() / val_total # 打印训练结果和验证结果 print( f'Epoch {epoch + 1}/{num_epochs}, Loss: {epoch_loss:.4f}, Train Acc: {epoch_acc:.4f}, Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}') # 如果当前验证准确率比之前的最佳准确率要好,保存当前权重 if val_acc > best_acc: best_acc = val_acc best_model_wts = model.state_dict() # 获取模型权重 测试模型 def test(): network.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: output = network(data) pred = output.data.max(1, keepdim=True)[1]    

最近访客

< 1/1 >

统计信息

已有6人来访过

  • 芯积分:40
  • 好友:--
  • 主题:3
  • 回复:7

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言