The Objective of This Article
This article will practice the PPOCR example in the RKNN Docker environment and deploy it to the RK3588 development board using the adb tool.
Development Environment Description
- Host System: Windows 11
- Target Device: Android development board equipped with the RK3588 chip
- Core Tools: Docker image containing rknn-toolkit2, rknn_model_zoo, and other tools, ADB debugging tools
PPOCR Directory Structure Description
The directory for the PPOCR example is located at rknn_model_zoo\examples\PPOCR, which contains three subdirectories described as follows:
1. PPOCR-Det
Core Functionality
Implements text area detection, improved based on the DB++ (Dynamic Binarization++) algorithm, supporting multi-scale feature fusion and adaptive threshold prediction.
Technical Features
- Adaptive Input Image Size controlled by the
<span>det_limit_side_len</span>
parameter with a maximum side length of 960 pixels, using<span>det_limit_type</span>
set to “max” mode for dynamic scaling - Post-processing Optimization includes differentiable binarization, Vatti Clipping polygon expansion (
<span>det_db_unclip_ratio=1.5</span>
), and other modules - Multi-algorithm Expansion supports post-processing parameter configuration for detection models such as EAST and SAST
2. PPOCR-Rec
Core Functionality
Implements text content recognition, using the SVTR (Scene Text Recognition with Transformer) architecture, supporting multi-language recognition.
Technical Features
- Input Specification images are uniformly scaled to
<span>3,48,320</span>
size, loading a dictionary file containing 6625 characters through<span>rec_char_dict_path</span>
- Dynamic Sequence Modeling uses a Transformer encoder to process variable-length text, supporting mixed training strategies for algorithms like CRNN and ABINet
- Quantization Optimization provides an INT8 quantization configuration scheme, compressing the model size from 11.9MB to 3.8MB
3. PPOCR-System
Core Functionality
An end-to-end OCR pipeline system that integrates detection, orientation classification, and recognition in three stages.
Workflow

Starting the RKNN Docker Environment
# Use the docker run command to create and run the RKNN Toolkit2 container
# and map local files into the container using the -v <host src folder>:<image dst folder> parameter
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb -v D:\rknn\rknn_model_zoo-v2.3.0:/rknn_model_zoo rknn-toolkit2:2.3.0-cp38 /bin/bash
Run the PPOCR-Det Example First
Download ppocrv4_det.onnx
cd /rknn_model_zoo/examples/PPOCR/PPOCR-Det/model
./download_model.sh
Execution Result:
Length: 4771801 (4.5M) [application/octet-stream]
Saving to: './ppocrv4_det.onnx'
./ppocrv4_det.onnx 100%[============================================================================>] 4.55M 1.36MB/s in 3.3s
2025-04-09 08:43:41 (1.36 MB/s) - './ppocrv4_det.onnx' saved [4771801/4771801]
Convert ONNX to RKNN Format
cd ../python
# python convert.py <onnx_model> <TARGET_PLATFORM> <dtype(optional)> <output_rknn_path(optional)>
python convert.py ../model/ppocrv4_det.onnx rk3588
Running Result:
I rknn-toolkit2 version: 2.3.0
--> Config model
done
--> Loading model
done
--> Building model
I Loading : 100%|█████████████████████████████████████████████| 342/342 [00:00<00:00, 119289.14it/s]
I OpFusing 0: 100%|██████████████████████████████████████████████| 100/100 [00:00<00:00, 706.50it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 340.48it/s]
I OpFusing 0 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 263.83it/s]
I OpFusing 1 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 250.24it/s]
I OpFusing 2 : 100%|█████████████████████████████████████████████| 100/100 [00:00<00:00, 167.88it/s]
I GraphPreparing : 100%|███████████████████████████████████████| 214/214 [00:00<00:00, 21065.53it/s]
I Quantizating : 100%|████████████████████████████████████████████| 214/214 [00:02<00:00, 72.65it/s]
I rknn building ...
I rknn building done.
done
# ls ../model/
download_model.sh ppocrv4_det.onnx ppocrv4_det.rknn test.jpg
Run the Android System C++ Example
1. Compile
# go back to the rknn_model_zoo root directory
cd ../../
./build-android.sh -t rk3588 -a arm64-v8a -d PPOCR-Det
Compilation succeeded without a doubt.
./build-android.sh -t rk3588 -a arm64-v8a -d PPOCR-Det
===================================
BUILD_DEMO_NAME=PPOCR-Det
BUILD_DEMO_PATH=examples/PPOCR/PPOCR-Det/cpp
TARGET_SOC=rk3588
TARGET_ARCH=arm64-v8a
BUILD_TYPE=Release
ENABLE_ASAN=OFF
DISABLE_RGA=
INSTALL_DIR=/rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo
BUILD_DIR=/rknn_model_zoo/build/build_rknn_PPOCR-Det_demo_rk3588_android_arm64-v8a_Release
ANDROID_NDK_PATH=/rknn_model_zoo/android-ndk-r19c
===================================
Install the project...
-- Install configuration: "Release"
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo/./rknn_ppocr_det_demo
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo/model/test.jpg
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo/model/ppocrv4_det.rknn
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo/lib/librknnrt.so
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo/lib/librga.so
2. Push to Development Board
# Switch to root user permissions
adb root
adb remount
adb push install/rk3588_android_arm64-v8a/rknn_PPOCR-Det_demo /data/rknn-test
3. Run Demo on Development Board
adb shell
# Enter the rknn_yolov5_demo directory on the development board
cd /data/rknn-test/rknn_PPOCR-Det_demo/
# Set the library environment
export LD_LIBRARY_PATH=./lib
# Run the executable
./rknn_ppocr_det_demo model/ppocrv4_det.rknn model/test.jpg
Running result is as follows:
rk3588_s:/data/rknn-test/rknn_PPOCR-Det_demo # chmod +x rknn_ppocr_det_demo
/rknn_ppocr_det_demo model/ppocrv4_det.rknn model/test.jpg <
model input num: 1, output num: 1
input tensors:
index=0, name=x, n_dims=4, dims=[1, 480, 480, 3], n_elems=691200, size=691200, fmt=NHWC, type=INT8, qnt_type=AFFINE, zp=-14, scale=0.018658
output tensors:
index=0, name=sigmoid_0.tmp_0, n_dims=4, dims=[1, 1, 480, 480], n_elems=230400, size=230400, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
model is NHWC input fmt
model input height=480, width=480, channel=3
origin size=500x500 crop size=496x496
input image: 500 x 500, subsampling: 4:4:4, colorspace: YCbCr, orientation: 1
src width is not 4/16-aligned, convert image use cpu
finish
rknn_run
DRAWING OBJECT
[0]: [(27, 459), (136, 459), (136, 478), (27, 478)] 0.990703
[1]: [(27, 428), (371, 428), (371, 446), (27, 446)] 0.865059
[2]: [(25, 397), (361, 395), (362, 413), (26, 415)] 0.947026
[3]: [(367, 368), (474, 366), (476, 386), (368, 388)] 0.988166
[4]: [(27, 363), (282, 365), (281, 384), (26, 382)] 0.952994
[5]: [(25, 334), (342, 334), (342, 352), (25, 352)] 0.955286
[6]: [(26, 303), (252, 303), (252, 320), (26, 320)] 0.977311
[7]: [(25, 270), (180, 270), (180, 289), (25, 289)] 0.995351
[8]: [(25, 240), (241, 240), (241, 259), (25, 259)] 0.987780
[9]: [(413, 233), (429, 233), (429, 305), (413, 305)] 0.977658
[10]: [(26, 209), (234, 209), (234, 227), (26, 227)] 0.999072
[11]: [(25, 179), (298, 177), (300, 194), (26, 195)] 0.991600
[12]: [(28, 142), (281, 144), (280, 163), (27, 161)] 0.963910
[13]: [(27, 111), (332, 113), (331, 134), (26, 133)] 0.929749
[14]: [(26, 82), (171, 82), (171, 104), (26, 104)] 0.997311
[15]: [(28, 37), (302, 39), (301, 70), (27, 69)] 0.961222
SAVE TO ./out.jpg
write_image path: ./out.jpg width=500 height=500 channel=3 data=0xb4000079e8295e50
Run the PPOCR-Rec Example Next
Download ONNX Model
cd /rknn_model_zoo/examples/PPOCR/PPOCR-Rec/model
./download_model.sh
Saving to: 'ppocrv4_rec.onnx'
ppocrv4_rec.onnx 100%[============================================================================>] 10.36M 2.52MB/s in 6.2s
2025-04-09 09:12:14 (1.67 MB/s) - 'ppocrv4_rec.onnx' saved [10862445/10862445]
Convert to RKNN Format
cd ../python
python convert.py ../model/ppocrv4_rec.onnx rk3588
# output model will be saved as ../model/ppocrv4_rec.rknn
Run C++ Demo (Android Development Board)
1. Compile
# go back to the rknn_model_zoo root directory
cd ../../
./build-android.sh -t rk3588 -a arm64-v8a -d PPOCR-Rec
Compilation succeeded without a doubt.
2. Push to Development Board
adb root
adb remount
adb push .\install\rk3588_android_arm64-v8a\rknn_PPOCR-Rec_demo\ /data/rknn-test
3. Run on Development Board
adb shell
cd /data/rknn-test/rknn_PPOCR-Rec_demo
export LD_LIBRARY_PATH=./lib
./rknn_ppocr_rec_demo model/ppocrv4_rec.rknn model/test.png
Running result:
model input num: 1, output num: 1
input tensors:
index=0, name=x, n_dims=4, dims=[1, 48, 320, 3], n_elems=46080, size=92160, fmt=NHWC, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000
output tensors:
index=0, name=softmax_11.tmp_0, n_dims=3, dims=[1, 40, 6625, 0], n_elems=265000, size=530000, fmt=UNDEFINED, type=FP16, qnt_type=AFFINE, zp=0, scale=1.000000
model is NHWC input fmt
model input height=48, width=320, channel=3
rknn_run
regconize result: JOINT, score=0.994140
Finally Run the PPOCR-System Example
Having downloaded and converted the detection and recognition ONNX models to RKNN format, let’s link the entire process together.
1. Compile
# go back to the rknn_model_zoo root directory
cd ../../
./build-android.sh -t rk3588 -a arm64-v8a -d PPOCR-System
Compilation Result:
Install the project...
-- Install configuration: "Release"
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/./rknn_ppocr_system_demo
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/model/test.jpg
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/model/ppocrv4_det.rknn
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/model/ppocrv4_rec.rknn
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/lib/librknnrt.so
-- Installing: /rknn_model_zoo/install/rk3588_android_arm64-v8a/rknn_PPOCR-System_demo/lib/librga.so
2. Push to Development Board
adb root
adb remount
adb push .\install\rk3588_android_arm64-v8a\rknn_PPOCR-System_demo\ /data/rknn-test
3. Run on Development Board
adb shell
cd /data/rknn-test/rknn_PPOCR-System_demo
export LD_LIBRARY_PATH=./lib
chmod +x rknn_ppocr_system_demo
./rknn_ppocr_system_demo model/ppocrv4_det.rknn model/ppocrv4_rec.rknn model/test.jpg
Note: The order of the models must be placed as above. Result:
model input height=48, width=320, channel=3
origin size=500x500 crop size=496x496
input image: 500 x 500, subsampling: 4:4:4, colorspace: YCbCr, orientation: 1
src width is not 4/16-aligned, convert image use cpu
DRAWING OBJECT
[0] @ [(28, 37), (302, 39), (301, 70), (27, 69)]
regconize result: Pure Nutrient Hair Conditioner, score=0.997977
[1] @ [(26, 82), (171, 82), (171, 104), (26, 104)]
regconize result: Product Information/Parameters, score=0.994559
[2] @ [(27, 111), (332, 113), (331, 134), (26, 133)]
regconize result: (45 yuan per kilogram, minimum order of 100 kilograms), score=0.971967
[3] @ [(28, 142), (281, 144), (280, 163), (27, 161)]
regconize result: 22 yuan per bottle, minimum order of 1000 bottles), score=0.981864
[4] @ [(25, 179), (298, 177), (300, 194), (26, 195)]
regconize result: [Brand]: OEM/ODM, score=0.986213
[5] @ [(26, 209), (234, 209), (234, 227), (26, 227)]
regconize result: [Product Name]: Pure Nutrient Hair Conditioner, score=0.996297
[6] @ [(25, 240), (241, 240), (241, 259), (25, 259)]
regconize result: [Product Number]: YM-X-3011, score=0.985657
[7] @ [(413, 233), (429, 233), (429, 305), (413, 305)]
regconize result: ODM/OEM, score=0.992676
[8] @ [(25, 270), (180, 270), (180, 289), (25, 289)]
regconize result: [Net Content]: 220ml, score=0.992010
[9] @ [(26, 303), (252, 303), (252, 320), (26, 320)]
regconize result: [Applicable People]: Suitable for all skin types, score=0.995155
[10] @ [(25, 334), (342, 334), (342, 352), (25, 352)]
regconize result: [Main Ingredients]: Cetyl Stearyl Alcohol, Oat Beta-Glucan, score=0.969624
[11] @ [(27, 363), (282, 365), (281, 384), (26, 382)]
regconize result: Sugar, Cocamidopropyl Betaine, Panthenol, score=0.925781
[12] @ [(367, 368), (474, 366), (476, 386), (368, 388)]
regconize result: (Finished Packaging Materials), score=0.986409
[13] @ [(25, 397), (361, 395), (362, 413), (26, 415)]
regconize result: [Main Function]: Can tighten the hair phospholipid layer, thus achieving, score=0.995605
[14] @ [(27, 428), (371, 428), (371, 446), (27, 446)]
regconize result: Instant and lasting improvement of hair shine, providing sufficient nourishment to dry hair, score=0.997995
[15] @ [(27, 459), (136, 459), (136, 478), (27, 478)]
regconize result: Hair sufficient nourishment, score=0.998616
SAVE TO ./out.jpg
write_image path: ./out.jpg width=500 height=500 channel=3 data=0xb400007c6db69e50