Go to file
leon 446c6cd638 fix(Readme): 优化了代码结构并更新了执行脚本
详细描述:

1.更新了Readme.md文件的说明信息,增加了上传和设置环境的步骤指导。
2025-02-11 15:53:31 +08:00
.idea first commit 2024-12-16 13:31:45 +08:00
cmake first commit 2024-12-16 13:31:45 +08:00
doc first commit 2024-12-16 13:31:45 +08:00
libapi fix(代码优化): 优化了yolov5数据处理过程中的内存使用 2025-01-25 10:29:05 +08:00
ss928sdk first commit 2024-12-16 13:31:45 +08:00
svp first commit 2024-12-16 13:31:45 +08:00
thridpart/ncnn first commit 2024-12-16 13:31:45 +08:00
.gitignore feat: 更新 .gitignore 文件以包含更多忽略项 2025-01-21 14:50:15 +08:00
build.sh first commit 2024-12-16 13:31:45 +08:00
CMakeLists.txt first commit 2024-12-16 13:31:45 +08:00
LICENSE first commit 2024-12-16 13:31:45 +08:00
Readme.md fix(Readme): 优化了代码结构并更新了执行脚本 2025-02-11 15:53:31 +08:00

wsl环境

1. 安装wsl

ubuntu版本必须为18.04。 windows打开powershell 输入以下命令不要使用cmd

wsl --install -d Ubuntu-18.04

安装参考地址:https://learn.microsoft.com/zh-cn/windows/wsl/install

2.正常安装928的开发环境参考指南。

3.修改目录

3.1 交叉编译工具

修改cmake/ss298.cmake目录交叉编译工具路径

SET(CMAKE_C_COMPILER   /opt/linux/x86-arm/aarch64-mix210-linux/bin/aarch64-mix210-linux-gcc)
SET(CMAKE_CXX_COMPILER /opt/linux/x86-arm/aarch64-mix210-linux/bin/aarch64-mix210-linux-g++)
SET(CMAKE_STRIP        /opt/linux/x86-arm/aarch64-mix210-linux/bin/aarch64-mix210-linux-strip)

3.2 修改CMakeLists.txt

把全部的/home/setups/ss928_framework/ 替换为自己wsl项目目录比如/mnt/d/ss928_framework/

4. 把虚拟机中相关目录拷贝wsl中同样的目录下

需要复制的目录为

  • /usr/local/lib
  • /usr/local/local
注意!!!,  注意!!!,  注意!!!,
    _.--""--._
    .'          `.
   /   O      O   \
  |    \  ^^  /    |
  \     `----'     /
   `. _______ .'
     //_____\\
    (( ____ ))
     `------'  

复制粘贴- /usr/local/lib/usr/local/local先打成压缩包再解压到wsl目录中直接从虚拟机中复制出来的时候会报错不支持符号链接的主机无法复制。

压缩并保持符号链接

cd /usr/local/lib
zip -ry ~/lib.zip ./*

cd /usr/local/include
zip -ry ~/include.zip ./*
  • -r 这个选项表示递归地处理目录
  • -y 保持符合链接

自行放到wsl任意目录,cd进入该目录解压。如需强制覆盖加上-o参数

sudo unzip lib.zip -d /usr/local/lib/
sudo unzip include.zip -d /usr/local/include/

把板子上相关目录拷贝wsl中同样的目录下

需要复制到目录为

  • /lib/aarch64-linux-gnu
  • /usr/lib/aarch64-linux-gnu
cd /lib/aarch64-linux-gnu
zip -ry ~/lib_agnu.zip ./*

cd /usr/lib/aarch64-linux-gnu
zip -ry ~/usr_lib_agnu.zip ./*

自行放到wsl任意目录,cd进入该目录解压。如需强制覆盖加上-o参数

sudo unzip lib_agnu.zip -d /lib/aarch64-linux-gnu/
sudo unzip usr_lib_agnu.zip -d /usr/lib/aarch64-linux-gnu/

cmake3.24版本

下载地址:https://cmake.org/files/v3.24/cmake-3.24.0-linux-aarch64.tar.gz 解压后的bin目录为可执行文件自行放到目录中。

5.编译

mkdir build
cd build
cmake ..
make -j(nproc)

build/libss928driver.so为生成的动态库文件

执行

上传

  • ss928sdk/lib 拷贝到 板端目录下
  • 将生成的动态库文件build/libss928driver.so拷贝到板端目录下
  • 将om模型文件拷贝到板端目录下
  • 自己要测试的图片以及下面所属的python脚本

你最终的目录结构应该是这样的

_test_928_batch.py   #脚本
best_sea_salt.om # 模型文件
lib/ # 库文件
libss928driver.so # 编译的动态库
ymj_sea_salt/   # 测试图片目录
ymj_sea_salt_result/ #结果图片目录

设置环境

# 设置环境变量能读取到lib的动态库
export LD_LIBRARY_PATH=${PWD}/lib:${PWD}/lib/npu:${PWD}/lib/svp_npu:$LD_LIBRARY_PATH
# fix ymj runtime oserror /usr/lib/aarch64-linux-gnu/libgomp.so.1: cannot allocate memory in static TLS block
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1:$LD_PRELOAD

创建conda环境

  • 将下面内容复制保存为environment.yaml,
  • 然后在板端执行conda env create -f environment.yaml
  • 创建完毕之后,激活环境conda activate ymj
name: ymj
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=51_gnu
  - anaconda-anon-usage=0.4.4=py312h7d20cce_100
  - archspec=0.2.3=pyhd3eb1b0_0
  - boltons=23.0.0=py312hd43f75c_0
  - brotli-python=1.0.9=py312h419075a_8
  - bzip2=1.0.8=h998d150_6
  - c-ares=1.19.1=h998d150_0
  - ca-certificates=2024.9.24=hd43f75c_0
  - certifi=2024.8.30=py312hd43f75c_0
  - cffi=1.17.1=py312hcb1262d_0
  - charset-normalizer=3.3.2=pyhd3eb1b0_0
  - conda=24.9.2=py312hd43f75c_0
  - conda-content-trust=0.2.0=py312hd43f75c_1
  - conda-libmamba-solver=24.9.0=pyhd3eb1b0_0
  - conda-package-handling=2.3.0=py312hd43f75c_0
  - conda-package-streaming=0.10.0=py312hd43f75c_0
  - cryptography=43.0.0=py312h5077475_0
  - distro=1.9.0=py312hd43f75c_0
  - expat=2.6.3=h419075a_0
  - fmt=9.1.0=hb8fdbf2_1
  - frozendict=2.4.2=py312hd43f75c_0
  - icu=73.1=h419075a_0
  - idna=3.7=py312hd43f75c_0
  - jsonpatch=1.33=py312hd43f75c_1
  - jsonpointer=2.1=pyhd3eb1b0_0
  - krb5=1.20.1=h2e2fba8_1
  - ld_impl_linux-aarch64=2.40=h48e3ba3_0
  - libarchive=3.7.4=h4086d46_0
  - libcurl=8.9.1=hfa2bbb0_0
  - libedit=3.1.20230828=h998d150_0
  - libev=4.33=hfd63f10_1
  - libffi=3.4.4=h419075a_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libmamba=1.5.8=h0a4e7f9_3
  - libmambapy=1.5.8=py312hd82f176_3
  - libnghttp2=1.57.0=hb788212_0
  - libsolv=0.7.24=h94b7715_1
  - libssh2=1.11.0=hfa2bbb0_0
  - libstdcxx-ng=11.2.0=h1234567_1
  - libuuid=1.41.5=h998d150_0
  - libxml2=2.13.1=h6097fa9_2
  - lz4-c=1.9.4=h419075a_1
  - menuinst=2.1.2=py312hd43f75c_0
  - ncurses=6.4=h419075a_0
  - openssl=3.0.15=h998d150_0
  - packaging=24.1=py312hd43f75c_0
  - pcre2=10.42=hcfaa891_1
  - pip=24.2=py312hd43f75c_0
  - platformdirs=3.10.0=py312hd43f75c_0
  - pluggy=1.0.0=py312hd43f75c_1
  - pybind11-abi=5=hd3eb1b0_0
  - pycosat=0.6.6=py312h998d150_1
  - pycparser=2.21=pyhd3eb1b0_0
  - pysocks=1.7.1=py312hd43f75c_0
  - python=3.12.7=h8edadfe_0
  - readline=8.2=h998d150_0
  - reproc=14.2.4=h419075a_2
  - reproc-cpp=14.2.4=h419075a_2
  - requests=2.32.3=py312hd43f75c_0
  - ruamel.yaml=0.18.6=py312h998d150_0
  - ruamel.yaml.clib=0.2.8=py312h998d150_0
  - setuptools=75.1.0=py312hd43f75c_0
  - sqlite=3.45.3=h998d150_0
  - tk=8.6.14=h987d8db_0
  - tqdm=4.66.5=py312h42ac6d5_0
  - truststore=0.8.0=py312hd43f75c_0
  - tzdata=2024b=h04d1e81_0
  - urllib3=2.2.3=py312hd43f75c_0
  - wheel=0.44.0=py312hd43f75c_0
  - xz=5.4.6=h998d150_1
  - yaml-cpp=0.8.0=h419075a_1
  - zlib=1.2.13=h998d150_1
  - zstandard=0.23.0=py312hc476304_0
  - zstd=1.5.6=h6a09583_0
  - pip:
      - colorlog==6.9.0
      - cython==3.0.11
      - numpy==2.1.3
      - opencv-python==4.10.0.84
      - pyzmq==26.2.0
      - simplejpeg==1.7.6
      - vidgear==0.3.3
prefix: /root/miniconda3/envs/ymj

python执行脚本

# -- coding: utf-8 --
import os
import sys
import subprocess
import ctypes
from ctypes import *
import platform
import time
import cv2
import numpy as np

from vidgear.gears import VideoGear
from vidgear.gears import NetGear

sys.path.append(r'./')


print(platform.architecture())


libss928 = ctypes.cdll.LoadLibrary("libss928driver.so")

class _TAROBJECT_(Structure):
    pass
_TAROBJECT_._fields_ = [
    ('x', c_int),              
    ('y', c_int), 
    ('width', c_int), 
    ('height', c_int), 
    ('label', c_int), 
    ('prob', c_float),            
    ('text', c_char * 256), 
]
TAROBJECT = _TAROBJECT_


class _RETURN_BOJECT_(Structure):
    pass
_RETURN_BOJECT_._fields_ = [
    ('count', c_int),
    ('objects', TAROBJECT * 128),
]
RETURN_BOJECT = _RETURN_BOJECT_


def LibapiSvpNpuHandleSig():
    libss928.LibapiSvpNpuHandleSig.argtype = c_void_p
    libss928.LibapiSvpNpuHandleSig.restype = c_uint
    return libss928.LibapiSvpNpuHandleSig()

def LibapiSvpNpuAclPrepareInit():
    libss928.LibapiSvpNpuAclPrepareInit.argtype = c_void_p
    libss928.LibapiSvpNpuAclPrepareInit.restype = c_uint
    return libss928.LibapiSvpNpuAclPrepareInit()

def LibApiSvpNpuAclPrepareExit():
    libss928.LibApiSvpNpuAclPrepareExit.argtype = c_void_p
    libss928.LibApiSvpNpuAclPrepareExit.restype = c_uint
    return libss928.LibApiSvpNpuAclPrepareExit()

def LibApiSvpNpuLoadModel(om_model_path, model_index, is_cached):
    libss928.LibApiSvpNpuLoadModel.argtype = (c_char_p, c_int, c_bool)
    libss928.LibApiSvpNpuLoadModel.restype = c_uint
    return libss928.LibApiSvpNpuLoadModel(om_model_path, model_index, is_cached)

def LibApiSvpNpuUnLoadModel(model_index):
    libss928.LibApiSvpNpuUnLoadModel.argtype = (c_int)
    libss928.LibApiSvpNpuUnLoadModel.restype = c_uint
    return libss928.LibApiSvpNpuUnLoadModel(model_index)

def LibApiSvpNpuLoadDataset(model_index, src, data_len, imgin_w, imgin_h, flag):
    libss928.LibApiSvpNpuLoadDataset.argtype = (c_int, c_void_p, c_int, c_int, c_int, c_int)
    libss928.LibApiSvpNpuLoadDataset.restype = c_uint
    return libss928.LibApiSvpNpuLoadDataset(model_index, src, data_len, imgin_w, imgin_h, flag)

def LibApiSvpNpuUnloadDataset():
    libss928.LibApiSvpNpuUnloadDataset.argtype = c_void_p
    libss928.LibApiSvpNpuUnloadDataset.restype = c_uint
    return libss928.LibApiSvpNpuUnloadDataset()

def LibApiSvpNpuModelExecute(model_index):
    libss928.LibApiSvpNpuModelExecute.argtype = (c_int)
    libss928.LibApiSvpNpuModelExecute.restype = c_uint
    return libss928.LibApiSvpNpuModelExecute(model_index)


def LibApiSvpNpuGetModelExecuteResult(model_index, retrunObject):
    libss928.LibApiSvpNpuGetModelExecuteResult.argtype = (c_uint , c_void_p)
    libss928.LibApiSvpNpuGetModelExecuteResult.restype = c_uint
    return libss928.LibApiSvpNpuGetModelExecuteResult(model_index, byref(retrunObject))


def _run_sh():
    os.chdir('/root/ss928_framework/build/output/')
    script_path = os.path.join('/root/ss928_framework/build/output/', 'rundemo.sh')
    print(script_path)
    try:
        result = subprocess.run(['source ' + script_path, script_path], shell=True)
        print("脚本执行成功")
    except subprocess.CalledProcessError as e:
        print(f"脚本执行失败,返回码: {e.returncode}")
        exit()

if __name__ == "__main__":

    options = { 
        "flag": 0, "copy": False, "track": False,
        "jpeg_compression": True,
        "jpeg_compression_quality": 90,
        "jpeg_compression_fastdct": True,
        "jpeg_compression_fastupsample": True
    }

    # 开启Netgear服务
    server = NetGear(
        address="192.168.101.46",
        port="5454",
        protocol="tcp",
        pattern=1,
        logging=True,
        **options
    )

    idxx = 0
    base_path = "./ymj_sea_salt/"  # 图片输入目录
    result_path = "./ymj_sea_salt_result/"  # 图片输出目录
    om_file_name = "best_sea_salt.om"
    
    # om_file_name = "best_hyp_add_samll_1_fp32_precision_mode_precision_mode.om"
    om_file_path = "./"

    # 确保输出目录存在
    if not os.path.exists(result_path):
        os.makedirs(result_path)

    # 获取所有图片文件
    image_files = [f for f in os.listdir(base_path) if f.lower().endswith(('jpg', 'jpeg', 'png'))]

    for image_file in image_files:
        try:
            if idxx == 0:
                LibapiSvpNpuHandleSig()
                LibapiSvpNpuAclPrepareInit()
                mpath = ctypes.c_char_p((om_file_path + om_file_name).encode('utf-8'))
                LibApiSvpNpuLoadModel(mpath, 0, False)
                idxx = 1

            # 读取当前图片
            frame = cv2.imread(os.path.join(base_path, image_file))
            # frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

            if frame is None:
                continue

            # 进行处理
            ptr = frame.ctypes.data_as(np.ctypeslib.ctypes.c_void_p)
            LibApiSvpNpuLoadDataset(0, ptr, frame.shape[0] * frame.shape[1] * frame.shape[2],
                                    frame.shape[1], frame.shape[0], cv2.CV_8UC3)

            LibApiSvpNpuModelExecute(0)

            # 获取分析结果
            return_objs = RETURN_BOJECT()
            res = LibApiSvpNpuGetModelExecuteResult(0, return_objs)
            print(f"LibApiSvpNpuGetModelExecuteResult.res====================================: {res}")
            print(f"objs.count====================================: {return_objs.count}")
            if return_objs.count > 0:
                for i in range(0, return_objs.count):
                    if i == 128: break
                    tarObject = return_objs.objects[i]

                    if tarObject.label == 0:
                        frame = cv2.rectangle(frame, (tarObject.x, tarObject.y + 20),
                                              (tarObject.x + tarObject.width, tarObject.y + 20 + tarObject.height),
                                              (0, 0, 255), 2)

            # 保存结果图像到新的目录,保持文件名不变
            result_file_path = os.path.join(result_path, image_file)
            cv2.imwrite(result_file_path, frame)

            # 清理
            LibApiSvpNpuUnloadDataset()

        except KeyboardInterrupt:
            break

    LibApiSvpNpuUnLoadModel(0)

执行

python _test_928_batch.py