├── README.md ├── android ├── AndroidManifest.xml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── res │ ├── drawable-ldpi │ │ ├── icon.png │ │ └── splash.png │ └── values │ │ └── libs.xml └── src │ └── com │ └── amin │ └── QtAndroidGallery │ └── QtAndroidGallery.java ├── assets ├── ManjaroMix.qss ├── ai.png ├── carmera.png ├── lena.png ├── nanodet.png └── picture.png ├── docs ├── 2022-02-04_105740.png ├── 2022-02-04_120855.png ├── 2022-02-04_121504.png ├── 2022-02-04_144250.png ├── 2022-02-04_150548.png ├── 2022-02-04_150705.png ├── Screenrecorder-2022-02-04-01-10-30-199.mp4 ├── Screenshot_2022-02-04-01-13-52-097_org.qtproject.example.png ├── Screenshot_2022-02-04-01-14-27-804_org.qtproject.example.png ├── Screenshot_2022-02-04-01-15-22-439_org.qtproject.example.png ├── bookmarks_ncnn.html ├── vs2019.png └── 新建文件夹 │ ├── 2022-02-04_143556.png │ ├── 2022-02-04_144010.png │ └── 2022-02-04_144117.png ├── main.cpp ├── model ├── nanodet_m.bin └── nanodet_m.param ├── mymainwindow.cpp ├── mymainwindow.h ├── mymainwindow.ui ├── pic.qrc ├── pic ├── ai.png ├── bus.jpg ├── carmera.png ├── lena.png ├── nanodet.png ├── picture.png └── start.png ├── yoloxncnn.pro └── yoloxncnn.pro.user /README.md: -------------------------------------------------------------------------------- 1 | ## Win10下QT+NCNN实现Android开发的踩坑记录 2 | 3 | **Xu Jing** 4 | 5 | 6 | ### 1.我为什么选择QT和NCNN? 7 | 8 | 作为算法工程师,比较惭愧的告诉大家我对JAVA不是很熟悉,对android和ios等移动端设备的开发也知之甚少,我有过的经验就是用Python的Kivy开发过若干Android程序, 9 | 用QT5的C++和Python版本开发过Windows和Linux桌面程序,同时研究过很多很多深度学习相关的算法,对深度学习模型的部署有一些研究心得,NCNN号称是在在移动端推断速度最快 10 | 的开源框架,我很想尝试一下。 11 | 为了尝试NCNN在移动端的部署,查了一圈资料基本都是Java+NCNN的栗子。没办法,我只能选择QT+NCNN。 12 | 13 | + 该项目的代码和编译的配置环境我将完全开源,希望对一些像我一样的小伙伴有帮助 14 | + 手摸手从零开始的环境搭建,干净又卫生 15 | 16 | 17 | ### 2.环境搭建 18 | 19 | + 1.QT: qt 5.14.2 20 | + 2.JDK: jdk8 21 | + 3.Android NDK: android-ndk r21 22 | + 4.Android JDK 23 | + 5.Opencv Android:opencv-4.1.0-android-sdk 24 | + 6.NCNN: ncnn-20211208-full-source.zip 25 | 26 | 27 | ### 3. QT编译环境配置 28 | 29 | #### #1.QT Android环境配置 30 | 31 | 该部分我们参考了B站教程:. 32 | 33 | + 下载section 1中的环境 34 | + 安装JDK8 35 | + 解压android-ndk r21 36 | + 解压android-jdk 37 | + 按照如下图配置QT 38 | 39 | ![](./docs/2022-02-04_105740.png) 40 | 41 | 42 | :zap: 为什么选择qt5.14.2和android-ndk r21 ? 43 | 44 | 为了方便和NCNN结合,在使用NCNN时发现 45 | 46 | 1. 用较低版本NDK编译失败,亲测用r15c可以,如果需要vulkan,需要ndk18以上,但是18以上不支持gcc了,默认clang 47 | 2. 较低版本Qt用gcc,高版本用clang,因此高版本应当可以直接用官方公布的最新的编译好的库,用不了的话再自己编译 48 | 49 | 因此我们选择了qt5.14.2和android-ndk r21. 50 | 51 | 52 | #### #2.QT OpenCV Android环境配置 53 | 54 | 我们尝试了opencv-android-sdk的不同版本,发现在qt5.14.2下opencv-4.1.0-android-sdk是可以正常工作的,因此我们最终选择opencv-android-sdk 55 | 56 | + 解压opencv-4.1.0-android-sdk.zip 57 | + 打开QtCreater按照如下步骤配置opencv的编译环境 58 | 59 | ![](./docs/2022-02-04_120855.png) 60 | 61 | ![](./docs/2022-02-04_121504.png) 62 | 63 | 为了方便大家配置,下面提供文本供复制 64 | ``` 65 | android { 66 | ANDROID_OPENCV = D:/QT/OpenCV-android-sdk/sdk/native 67 | #ANDROID_OPENCV = D:/NCNN/opencv-mobile-4.5.1-android/sdk/native 68 | INCLUDEPATH += \ 69 | $$ANDROID_OPENCV/jni/include/opencv2 \ 70 | $$ANDROID_OPENCV/jni/include \ 71 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/include \ 72 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/include/ncnn 73 | 74 | 75 | LIBS += \ 76 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_ml.a \ 77 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_objdetect.a \ 78 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_calib3d.a \ 79 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a \ 80 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a \ 81 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a \ 82 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_flann.a \ 83 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a \ 84 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_dnn.a \ 85 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a \ 86 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libcpufeatures.a \ 87 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libIlmImf.a \ 88 | #$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjasper.a \ 89 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjpeg-turbo.a \ 90 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibpng.a \ 91 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibprotobuf.a \ 92 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibtiff.a \ 93 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibwebp.a \ 94 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libquirc.a \ 95 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtbb.a \ 96 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtegra_hal.a \ 97 | $$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_java4.so \ 98 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/lib/libncnn.a \ 99 | D:/QT/android-ndk-r21/platforms/android-28/arch-arm/usr/lib/libandroid.so \ 100 | D:/QT/android-ndk-r21/toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.8/lib/linux/arm/libomp.a \ 101 | D:/QT/android-ndk-r21/toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.8/lib/linux/arm/libomp.so 102 | 103 | # opencv-mobile配置 已废弃 104 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a \ 105 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a \ 106 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a \ 107 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a \ 108 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_photo.a \ 109 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a \ 110 | 111 | # add other file to assets 112 | 113 | data.files += pic/nanodet.png 114 | data.files += pic/ai.png 115 | data.files += pic/carmera.png 116 | data.files += pic/picture.png 117 | data.files += pic/bus.jpg 118 | data.files += model/nanodet_m.param 119 | data.files += model/nanodet_m.bin 120 | 121 | data.path = /assets/pic 122 | INSTALLS += data 123 | 124 | } 125 | ``` 126 | 127 | 128 | :zap: 为什么没有选择 [opencv-mobile](https://github.com/nihui/opencv-mobile) ? 129 | 130 | 首先要说明一下,为什么在opencv-android-sdk正常编译的情况下考虑使用opencv-mobile,原因有两个其中一个原因是opencv-mobile比opencv-android-sdk要小,且包含了我们常用的一些opencv功能,比如: 131 | 132 | + 提供 android 和 ios 平台最小化编译的 opencv 库 133 | + 提供 opencv 2.4.13.7 和 3.4.13 和 4.5.1 三种版本的预编译包 134 | + 提供官方 opencv 缺少的 ios bitcode 版本的预编译包 135 | + 包含基础的 opencv Mat 和矩阵操作,常用的图像处理功能 136 | + 禁用了 C++ RTTI 和 exceptions 137 | 138 | 第二个原因是最主要的原因,就像上述最后一条提到的,opencv-mobile库禁用了C++ RTTI和exceptions,而opencv-android-sdk是需要开启的,在QT中同时使用opencv和ncnn中关于C++ RTTI和exceptions这两个库是有冲突的,特别在使用自定义的层时(比如YOLOv5和YOLOX中的自定义层)ncnn需要禁用C++ RTTI和exceptions.这里nihui大佬个我们提供了[两个解决方案](https://github.com/Tencent/ncnn/issues/2694): 139 | ``` 140 | 是否有同时用到 opencv 库?官方的 opencv 库是需要开启 rtti 的,这和目前 ncnn 的预编译包在使用自定义层时会不兼容 141 | 第一种方法是使用 NCNN_DISABLE_RTTI=OFF 自己编译下ncnn库 142 | 第二种方法是编译你的so时 -fno-rtti -fno-exceptions,可以配合 https://github.com/nihui/opencv-mobile 使用,像这样: 143 | #QMAKE_CFLAGS += -fno-rtti 144 | #QMAKE_CXXFLAGS += -fno-rtti 145 | ``` 146 | 147 | 现在说一下为什么我最终没有选择,当我把4.5.1的编译版本用在QT中时,会提示我一些错误,错误类型在该issues:,最终我没有解决,因此放弃了使用opencv-mobile. 148 | 149 | 150 | #### #3.NCNN vs2019编译 151 | 152 | nihui提供了各种编译的版本在ncnn官方repo的release中,我们下载了[ncnn-20211208-full-source.zip](https://github.com/Tencent/ncnn/releases),并在vs2019中重新编译. 153 | 154 | + 编译protobuf 3.4.0 155 | 156 | Protobuf是一种平台无关、语言无关、可扩展且轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。 157 | 从[该地址](https://github.com/google/protobuf/archive/v3.4.0.zip)下载protobuf3.4.0的压缩包,解压后放在之前新建的文件中,然后在开始菜单找到`Visual Studio 2019=>x64 Native Tools Command Prompt for VS 2019右击,点击更多,以管理员身份运行`,输入以下命令编译protobuf3.4.0: 158 | 159 | 160 | ``` 161 | cd 162 | mkdir build-vs2019 163 | cd build-vs2019 164 | cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ../cmake 165 | nmake 166 | nmake install 167 | 168 | ``` 169 | 其中protobuf-root-dir是你的protobuf解压的路径. 安装完成后的build-vs2019文件夹,之后编译ncnn的时候需要用到. 170 | 171 | + 安装VulkanSDK 1.2.148.0 172 | 173 | 我们这次并没有开启ncnn的Vulkan,但是为了完整的安装,该步骤我们在这里也提供給大家.vulkan是新一代的图形和计算API,它提供了对现代图形处理器的高效、跨平台访问,这些图形处理器应用于各种各样的设备,从pc和主机到移动电话和嵌入式平台。ncnn支持vulkan使用gpu进行加速。当然如果在编译ncnn的时候如果不想使用gpu可跳过此步骤。从下载处下载VulkanSDK 1.2.148.0 的win安装版本。下载完成后一键安装。 174 | 175 | + 编译ncnn框架-ncnn-full-source 176 | 177 | 在ncnn-release中下载ncnn-full-source.zip。 在开始菜单找到`Visual Studio 2019=>x64 Native Tools Command Prompt for VS 2019`右击,点击更多,以管理员身份运行,输入以下命令编译ncnn: 178 | ``` 179 | 180 | cd 181 | mkdir build-vs2019 182 | cd build-vs2019 183 | cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install 184 | -DProtobuf_INCLUDE_DIR=/build-vs2019/install/include 185 | -DProtobuf_LIBRARIES=/build-vs2019/install/lib/libprotobuf.lib 186 | -DProtobuf_PROTOC_EXECUTABLE=/build-vs2019/install/bin/protoc.exe 187 | -DNCNN_VULKAN=OFF .. -DOpenCV_DIR=/build 188 | nmake 189 | nmake install 190 | 191 | ``` 192 | 193 | 其中 ``是ncnn-full-source的根目录,``是protobuf的根目录,``是opencv的根目录,如果之前放在一个目录下面的话就很容易管理。如果不想使用vulkan,可以将`-DNCNN_VULKAN=OFF`。 194 | 195 | 如果没有报错,恭喜你ncnn编译成功了! 196 | 197 | 为了验证我们编译的ncnn时可用的,我们创建了一个YOLOX的测试项目,在VS2019中进行测试,在VS2019中做如下配置: 198 | 199 | ![](./docs/vs2019.png) 200 | 201 | 可以正常识别: 202 | ![](./docs/2022-02-04_144250.png) 203 | 204 | 205 | 206 | #### #4.NCNN Android编译 207 | 208 | 209 | + 我们已经安装了android-ndk-r21 210 | + 在开始菜单找到`Visual Studio 2019=>x64 Native Tools Command Prompt for VS 2019`右击,点击更多,以管理员身份运行 211 | + `export ANDROID_NDK=` 212 | + build ncnn android 213 | 214 | ``` 215 | cd 216 | mkdir -p build-android-armv7 217 | cd build-android-armv7 218 | 219 | cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ 220 | -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON NCNN_DISABLE_RTTI=OFF\ 221 | -DANDROID_PLATFORM=android-28 .. 222 | 223 | # If you want to enable Vulkan, platform api version >= android-24 is needed 224 | cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ 225 | -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \ 226 | -DANDROID_PLATFORM=android-24 -DNCNN_VULKAN=ON .. 227 | 228 | make -j$(nproc) 229 | make install 230 | ``` 231 | 232 | :zap: 为什么要选择重新编译ncnn ? 233 | 234 | + 官方编译的有些参数是没有打开的,有些参数是我们项目暂时不需要需要编译过程中关闭的 235 | + 编译安卓版本需要关闭C++ RTTI 236 | 237 | 238 | 最后我们将编译好的安卓NCNN库链接到QT 239 | 240 | ![](docs/2022-02-04_150548.png) 241 | ![](docs/2022-02-04_150705.png) 242 | 243 | :zap: 为什么要链接:`libandroid.so`和`libomp.so`? 244 | 245 | 链接libandroid.so是因为我们会将模型文件一起打包到apk中的assets中,ncnn模型加载中需要libandroid.so库,链接libomp.so是因为ncnn中的多线程中用到了该库,需要链接,否则编译过程中会报错。 246 | 247 | 248 | :zap: pro中要加入openmp(不加编译报错) 249 | 250 | ``` 251 | QMAKE_CXXFLAGS += -fopenmp 252 | QMAKE_LFLAGS += -fopenmp 253 | LIBS += -fopenmp -lgomp 254 | ``` 255 | 256 | 257 | #### #5.QT android调用手机相册和摄像头 258 | 259 | 用QT的原生发发我们测试发现是无法获得android相册中图片的路径的,比如如下代码: 260 | 261 | ``` 262 | //在android中是不work的 263 | QString fileName = QFileDialog::getOpenFileName(this, tr("打开图片"), "assets:/pic", tr("Image Files(*.jpg *.png *.bmp *.pgm *.pbm);;All(*.*)")); 264 | qDebug() << "fileName: " << fileName ; 265 | QMessageBox::information(NULL, "选择的图片路径", fileName, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); 266 | 267 | ``` 268 | 269 | 参考,实现在QT中加载android相册图片和调用摄像头获取图片。 270 | 271 | + 将QtAndroidGallery.java文件copy到`./ardroid/src/com/amin/QtAndroidFallery/QtAndroidGallery.java` 272 | + 修改`AndroidManifest.xml` 273 | 274 | ``` 275 | 276 | ``` 277 | 278 | + pro中增加 279 | ``` 280 | QT += core gui 281 | QT += androidextras 282 | ``` 283 | + 获取Android相册和相机 284 | 285 | ``` 286 | //获取android 相册 287 | QString selectedFileName; 288 | cv::Mat Img2Det; 289 | 290 | #ifdef __cplusplus 291 | extern "C" { 292 | #endif 293 | 294 | JNIEXPORT void JNICALL 295 | Java_com_amin_QtAndroidGallery_QtAndroidGallery_fileSelected(JNIEnv */*env*/, 296 | jobject /*obj*/, 297 | jstring results) 298 | { 299 | selectedFileName = QAndroidJniObject(results).toString(); 300 | } 301 | 302 | #ifdef __cplusplus 303 | } 304 | #endif 305 | 306 | // 相册 307 | selectedFileName = "#"; 308 | QAndroidJniObject::callStaticMethod("com/amin/QtAndroidGallery/QtAndroidGallery", 309 | "openAnImage", 310 | "()V"); 311 | while(selectedFileName == "#") 312 | qApp->processEvents(); 313 | 314 | qDebug()<<"file name:"<label_2->setPixmap(QPixmap::fromImage(img)); 319 | 320 | cv::Mat img = cv::imread(selectedFileName.toStdString()); 321 | LabelDisplayMat(ui->label_2,img); 322 | Img2Det = img.clone(); 323 | } 324 | 325 | 326 | //相机 327 | 328 | selectedFileName = "#"; 329 | QAndroidJniObject::callStaticMethod("com/amin/QtAndroidGallery/QtAndroidGallery", 330 | "captureAnImage", 331 | "()V"); 332 | while(selectedFileName == "#") 333 | qApp->processEvents(); 334 | 335 | if(selectedFileName != "#") 336 | { 337 | if(QFile(selectedFileName).exists()){ 338 | cv::Mat img = cv::imread(selectedFileName.toStdString()); 339 | LabelDisplayMat(ui->label_2,img); 340 | Img2Det = img.clone(); 341 | } 342 | 343 | } 344 | 345 | 346 | ``` 347 | 348 | ### 4.关于代码部分的一些说明 349 | 350 | + ncnn模型部分不应该这样应该有个模型类实现并在程序开启时加载模型 351 | 352 | 因为时间关系,我们仅仅是为了实现QT下调用ncnn和opencv在安卓上实现AI识别,代码结构需要后续调整,比如模型识别类的实现,模型在程序开机过程中预先加载,模型加密等。 353 | 354 | + 没有使用Vulkan,编译部分为了简单起见我都关闭掉了 355 | 356 | 本次编译我们并没有打开Vulkan, 如果需要可以在ncnn编译过程中打开该选项。 357 | 358 | + 怎样解决像YOLO v5或YOLOX这种调用自定义层的方式 359 | 360 | 在环境配置中我们说到因为该项目我们同时使用到了opencv和ncnn,默认opencv是需要开启C++ rtti 的,这和目前ncnn的预编译包在使用自定义层时是不兼容的,解决办法: 361 | 362 | ``` 363 | 第一种方法是使用 NCNN_DISABLE_RTTI=OFF 自己编译下ncnn库 364 | 第二种方法是编译你的so时 -fno-rtti -fno-exceptions,可以配合 https://github.com/nihui/opencv-mobile 使用,像这样: 365 | #QMAKE_CFLAGS += -fno-rtti 366 | #QMAKE_CXXFLAGS += -fno-rtti 367 | ``` 368 | 369 | + 为什么没有选择qml 370 | 371 | qml用的不熟 372 | 373 | + 为什么项目名称是YOLOX而最终是NanoDet 374 | 375 | 开始规划是使用YOLOX作为ncnn调用识别的模型的,并且该部分代码我们在ncnn编译过程中的测试时已经实现,但因为其自定义层需要解决rtti的问题,简单起见我们选择将该模型替换为简单的NanoDet. 376 | 377 | 378 | ### 5.吸收了哪些大神们的精华 379 | 380 | + nihui的知乎: 381 | + 知乎大佬多ncnn的总结: 382 | + ncnn的官方repo: 383 | + ncnn的模型仓库: 384 | + ncnn的编译: 385 | + QT+opencv android的配置: 386 | + QT+ncnn的配置: 387 | + QT安卓环境配置: 388 | + QT修改android程序的图标和名字: 389 | + QT打包文件到安卓程序: 390 | + QT打开安卓相册: 391 | + QT打开安卓摄像头: 392 | 393 | 394 | ### 6. `F**K ` QT + NCNN终于成功在小米手机上跑起来了 395 | 396 | 397 | + 打开相册进行识别 398 | 399 | ![](./docs/Screenshot_2022-02-04-01-13-52-097_org.qtproject.example.png) 400 | 401 | 402 | + 打开摄像头进行识别 403 | 404 | ![](./docs/Screenshot_2022-02-04-01-15-22-439_org.qtproject.example.png) 405 | 406 | + 测试的视频参考: 407 | 408 | 409 | ### 7. APK下载 410 | 411 | :bug: [APK-Download](https://github.com/DataXujing/Qt_NCNN_NanoDet/releases/download/untagged-72f6072efe822df13658/nanodet-ncnn-release.apk) 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | repositories { 13 | google() 14 | jcenter() 15 | } 16 | 17 | apply plugin: 'com.android.application' 18 | 19 | dependencies { 20 | implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) 21 | } 22 | 23 | android { 24 | /******************************************************* 25 | * The following variables: 26 | * - androidBuildToolsVersion, 27 | * - androidCompileSdkVersion 28 | * - qt5AndroidDir - holds the path to qt android files 29 | * needed to build any Qt application 30 | * on Android. 31 | * 32 | * are defined in gradle.properties file. This file is 33 | * updated by QtCreator and androiddeployqt tools. 34 | * Changing them manually might break the compilation! 35 | *******************************************************/ 36 | 37 | compileSdkVersion androidCompileSdkVersion.toInteger() 38 | 39 | buildToolsVersion '28.0.3' 40 | 41 | sourceSets { 42 | main { 43 | manifest.srcFile 'AndroidManifest.xml' 44 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] 45 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] 46 | res.srcDirs = [qt5AndroidDir + '/res', 'res'] 47 | resources.srcDirs = ['resources'] 48 | renderscript.srcDirs = ['src'] 49 | assets.srcDirs = ['assets'] 50 | jniLibs.srcDirs = ['libs'] 51 | } 52 | } 53 | 54 | lintOptions { 55 | abortOnError false 56 | } 57 | 58 | // Do not compress Qt binary resources file 59 | aaptOptions { 60 | noCompress 'rcc' 61 | } 62 | 63 | defaultConfig { 64 | resConfigs "en" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/android/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /android/res/drawable-ldpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/android/res/drawable-ldpi/splash.png -------------------------------------------------------------------------------- /android/res/values/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://download.qt.io/ministro/android/qt5/qt-5.14 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /android/src/com/amin/QtAndroidGallery/QtAndroidGallery.java: -------------------------------------------------------------------------------- 1 | package com.amin.QtAndroidGallery; 2 | 3 | import org.qtproject.qt5.android.bindings.QtApplication; 4 | import org.qtproject.qt5.android.bindings.QtActivity; 5 | 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.database.Cursor; 9 | import android.graphics.Bitmap; 10 | import android.graphics.BitmapFactory; 11 | import android.net.Uri; 12 | import android.os.Bundle; 13 | import android.os.Environment; 14 | import android.provider.MediaStore; 15 | import android.util.Log; 16 | import android.os.Build; 17 | import android.os.Build.VERSION; 18 | import android.widget.Toast; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.text.SimpleDateFormat; 23 | import java.util.ArrayList; 24 | import java.util.Date; 25 | import java.util.List; 26 | import android.provider.DocumentsContract; 27 | import android.content.ContentUris; 28 | 29 | public class QtAndroidGallery extends QtActivity 30 | { 31 | 32 | public static native void fileSelected(String fileName); 33 | 34 | static final int REQUEST_OPEN_IMAGE = 1; 35 | public String lastCameraFileUri; 36 | static final int REQUEST_CAPTURE_IMAGE = 2; 37 | 38 | private static QtAndroidGallery m_instance; 39 | 40 | public QtAndroidGallery() 41 | { 42 | m_instance = this; 43 | } 44 | 45 | @Override 46 | public void onCreate(Bundle savedInstanceState) 47 | { 48 | super.onCreate(savedInstanceState); 49 | } 50 | 51 | @Override 52 | protected void onDestroy() 53 | { 54 | super.onDestroy(); 55 | } 56 | 57 | static void openAnImage() 58 | { 59 | m_instance.dispatchOpenGallery(); 60 | } 61 | 62 | @Override 63 | protected void onActivityResult(int requestCode, int resultCode, Intent data) 64 | { 65 | if (resultCode == RESULT_OK) 66 | { 67 | if(requestCode == REQUEST_OPEN_IMAGE) 68 | { 69 | System.out.println("debug 123456789"); 70 | String filePath = getPath(getApplicationContext(), data.getData()); 71 | fileSelected(filePath); 72 | } 73 | else if(requestCode == REQUEST_CAPTURE_IMAGE) 74 | { 75 | String filePath = lastCameraFileUri; 76 | fileSelected(filePath); 77 | } 78 | } 79 | else 80 | { 81 | fileSelected(":("); 82 | } 83 | 84 | super.onActivityResult(requestCode, resultCode, data); 85 | } 86 | 87 | private void dispatchOpenGallery() 88 | { 89 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 90 | intent.setType("image/*"); 91 | startActivityForResult(intent, REQUEST_OPEN_IMAGE); 92 | } 93 | 94 | public String getRealPathFromURI(Context context, Uri contentUri) 95 | { 96 | Cursor cursor = null; 97 | try 98 | { 99 | String[] proj = { MediaStore.Images.Media.DATA }; 100 | cursor = context.getContentResolver().query(contentUri, proj, null, null, null); 101 | int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 102 | cursor.moveToFirst(); 103 | return cursor.getString(column_index); 104 | } 105 | finally 106 | { 107 | if (cursor != null) 108 | { 109 | cursor.close(); 110 | } 111 | } 112 | } 113 | 114 | 115 | 116 | /** 117 | * Get a file path from a Uri. This will get the the path for Storage Access 118 | * Framework Documents, as well as the _data field for the MediaStore and 119 | * other file-based ContentProviders. 120 | * 121 | * @param context The context. 122 | * @param uri The Uri to query. 123 | * @author paulburke 124 | */ 125 | public static String getPath(final Context context, final Uri uri) { 126 | 127 | final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 128 | 129 | // DocumentProvider 130 | if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { 131 | // ExternalStorageProvider 132 | if (isExternalStorageDocument(uri)) { 133 | final String docId = DocumentsContract.getDocumentId(uri); 134 | final String[] split = docId.split(":"); 135 | final String type = split[0]; 136 | 137 | if ("primary".equalsIgnoreCase(type)) { 138 | return Environment.getExternalStorageDirectory() + "/" + split[1]; 139 | } 140 | 141 | // TODO handle non-primary volumes 142 | } 143 | // DownloadsProvider 144 | else if (isDownloadsDocument(uri)) { 145 | 146 | final String id = DocumentsContract.getDocumentId(uri); 147 | final Uri contentUri = ContentUris.withAppendedId( 148 | Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 149 | 150 | return getDataColumn(context, contentUri, null, null); 151 | } 152 | // MediaProvider 153 | else if (isMediaDocument(uri)) { 154 | final String docId = DocumentsContract.getDocumentId(uri); 155 | final String[] split = docId.split(":"); 156 | final String type = split[0]; 157 | 158 | Uri contentUri = null; 159 | if ("image".equals(type)) { 160 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 161 | } else if ("video".equals(type)) { 162 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 163 | } else if ("audio".equals(type)) { 164 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 165 | } 166 | 167 | final String selection = "_id=?"; 168 | final String[] selectionArgs = new String[] { 169 | split[1] 170 | }; 171 | 172 | return getDataColumn(context, contentUri, selection, selectionArgs); 173 | } 174 | } 175 | // MediaStore (and general) 176 | else if ("content".equalsIgnoreCase(uri.getScheme())) { 177 | return getDataColumn(context, uri, null, null); 178 | } 179 | // File 180 | else if ("file".equalsIgnoreCase(uri.getScheme())) { 181 | return uri.getPath(); 182 | } 183 | 184 | return null; 185 | } 186 | 187 | /** 188 | * Get the value of the data column for this Uri. This is useful for 189 | * MediaStore Uris, and other file-based ContentProviders. 190 | * 191 | * @param context The context. 192 | * @param uri The Uri to query. 193 | * @param selection (Optional) Filter used in the query. 194 | * @param selectionArgs (Optional) Selection arguments used in the query. 195 | * @return The value of the _data column, which is typically a file path. 196 | */ 197 | public static String getDataColumn(Context context, Uri uri, String selection, 198 | String[] selectionArgs) { 199 | 200 | Cursor cursor = null; 201 | final String column = "_data"; 202 | final String[] projection = { 203 | column 204 | }; 205 | 206 | try { 207 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, 208 | null); 209 | if (cursor != null && cursor.moveToFirst()) { 210 | final int column_index = cursor.getColumnIndexOrThrow(column); 211 | return cursor.getString(column_index); 212 | } 213 | } finally { 214 | if (cursor != null) 215 | cursor.close(); 216 | } 217 | return null; 218 | } 219 | 220 | 221 | /** 222 | * @param uri The Uri to check. 223 | * @return Whether the Uri authority is ExternalStorageProvider. 224 | */ 225 | public static boolean isExternalStorageDocument(Uri uri) { 226 | return "com.android.externalstorage.documents".equals(uri.getAuthority()); 227 | } 228 | 229 | /** 230 | * @param uri The Uri to check. 231 | * @return Whether the Uri authority is DownloadsProvider. 232 | */ 233 | public static boolean isDownloadsDocument(Uri uri) { 234 | return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 235 | } 236 | 237 | /** 238 | * @param uri The Uri to check. 239 | * @return Whether the Uri authority is MediaProvider. 240 | */ 241 | public static boolean isMediaDocument(Uri uri) { 242 | return "com.android.providers.media.documents".equals(uri.getAuthority()); 243 | } 244 | 245 | 246 | static void captureAnImage() 247 | { 248 | m_instance.dispatchTakePictureIntent(); 249 | } 250 | 251 | private void dispatchTakePictureIntent() 252 | { 253 | Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 254 | 255 | // Ensure that there’s a camera activity to handle the intent 256 | if (takePictureIntent.resolveActivity(getPackageManager()) != null) 257 | { 258 | // Create the File where the photo should go 259 | File photoFile = null; 260 | try 261 | { 262 | photoFile = m_instance.createImageFile(); 263 | } 264 | catch (IOException ex) 265 | { 266 | // Error occurred while creating the File 267 | Toast.makeText(QtAndroidGallery.this, ex.getLocalizedMessage(), Toast.LENGTH_LONG).show(); 268 | Toast.makeText(QtAndroidGallery.this, ex.getMessage(), Toast.LENGTH_LONG).show(); 269 | } 270 | // Continue only if the File was successfully created 271 | if (photoFile != null) 272 | { 273 | takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); 274 | 275 | lastCameraFileUri = photoFile.toString(); 276 | 277 | startActivityForResult(takePictureIntent, REQUEST_CAPTURE_IMAGE); 278 | } 279 | } 280 | else 281 | { 282 | Toast.makeText(QtAndroidGallery.this, "Problems with your camera?!", Toast.LENGTH_SHORT).show(); 283 | } 284 | } 285 | 286 | 287 | private File createImageFile() throws IOException 288 | { 289 | // Create an image file name 290 | String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 291 | String imageFileName = "MYAPPTEMP_" + timeStamp + "_"; 292 | File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); 293 | File image = File.createTempFile(imageFileName, /* prefix */ 294 | ".jpg", /* suffix */ 295 | storageDir /* directory */ 296 | ); 297 | 298 | return image; 299 | } 300 | 301 | 302 | } 303 | 304 | 305 | -------------------------------------------------------------------------------- /assets/ManjaroMix.qss: -------------------------------------------------------------------------------- 1 | /* 2 | ManjaroMix Style Sheet for QT Applications 3 | Author: Jaime A. Quiroga P. 4 | Company: GTRONICK 5 | Last updated: 25/02/2020, 15:42. 6 | Available at: https://github.com/GTRONICK/QSS/blob/master/ManjaroMix.qss 7 | */ 8 | QMainWindow { 9 | background-color:#151a1e; 10 | } 11 | QCalendar { 12 | background-color: #151a1e; 13 | } 14 | QTextEdit { 15 | border-width: 1px; 16 | border-style: solid; 17 | border-color: #4fa08b; 18 | background-color: #222b2e; 19 | color: #d3dae3; 20 | } 21 | QPlainTextEdit { 22 | border-width: 1px; 23 | border-style: solid; 24 | border-color: #4fa08b; 25 | background-color: #222b2e; 26 | color: #d3dae3; 27 | } 28 | QToolButton { 29 | border-style: solid; 30 | border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 31 | border-right-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(217, 217, 217), stop:1 rgb(227, 227, 227)); 32 | border-left-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(227, 227, 227), stop:1 rgb(217, 217, 217)); 33 | border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 34 | border-width: 1px; 35 | border-radius: 5px; 36 | color: #d3dae3; 37 | padding: 2px; 38 | background-color: rgb(255,255,255); 39 | } 40 | QToolButton:hover{ 41 | border-style: solid; 42 | border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(195, 195, 195), stop:1 rgb(222, 222, 222)); 43 | border-right-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(197, 197, 197), stop:1 rgb(227, 227, 227)); 44 | border-left-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(227, 227, 227), stop:1 rgb(197, 197, 197)); 45 | border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(195, 195, 195), stop:1 rgb(222, 222, 222)); 46 | border-width: 1px; 47 | border-radius: 5px; 48 | color: rgb(0,0,0); 49 | padding: 2px; 50 | background-color: rgb(255,255,255); 51 | } 52 | QToolButton:pressed{ 53 | border-style: solid; 54 | border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 55 | border-right-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(217, 217, 217), stop:1 rgb(227, 227, 227)); 56 | border-left-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(227, 227, 227), stop:1 rgb(217, 217, 217)); 57 | border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 58 | border-width: 1px; 59 | border-radius: 5px; 60 | color: rgb(0,0,0); 61 | padding: 2px; 62 | background-color: rgb(142,142,142); 63 | } 64 | QPushButton{ 65 | border-style: solid; 66 | border-color: #050a0e; 67 | border-width: 1px; 68 | border-radius: 5px; 69 | color: #d3dae3; 70 | padding: 2px; 71 | background-color: #151a1e; 72 | } 73 | QPushButton::default{ 74 | border-style: solid; 75 | border-color: #050a0e; 76 | border-width: 1px; 77 | border-radius: 5px; 78 | color: #FFFFFF; 79 | padding: 2px; 80 | background-color: #151a1e;; 81 | } 82 | QPushButton:hover{ 83 | border-style: solid; 84 | border-color: #050a0e; 85 | border-width: 1px; 86 | border-radius: 5px; 87 | color: #d3dae3; 88 | padding: 2px; 89 | background-color: #1c1f1f; 90 | } 91 | QPushButton:pressed{ 92 | border-style: solid; 93 | border-color: #050a0e; 94 | border-width: 1px; 95 | border-radius: 5px; 96 | color: #d3dae3; 97 | padding: 2px; 98 | background-color: #2c2f2f; 99 | } 100 | QPushButton:disabled{ 101 | border-style: solid; 102 | border-top-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 103 | border-right-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(217, 217, 217), stop:1 rgb(227, 227, 227)); 104 | border-left-color: qlineargradient(spread:pad, x1:0, y1:0.5, x2:1, y2:0.5, stop:0 rgb(227, 227, 227), stop:1 rgb(217, 217, 217)); 105 | border-bottom-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgb(215, 215, 215), stop:1 rgb(222, 222, 222)); 106 | border-width: 1px; 107 | border-radius: 5px; 108 | color: #808086; 109 | padding: 2px; 110 | background-color: rgb(142,142,142); 111 | } 112 | QLineEdit { 113 | border-width: 1px; 114 | border-style: solid; 115 | border-color: #4fa08b; 116 | background-color: #222b2e; 117 | color: #d3dae3; 118 | } 119 | QLabel { 120 | color: #d3dae3; 121 | } 122 | QLCDNumber { 123 | color: #4d9b87; 124 | } 125 | QProgressBar { 126 | text-align: center; 127 | color: #d3dae3; 128 | border-radius: 10px; 129 | border-color: transparent; 130 | border-style: solid; 131 | background-color: #52595d; 132 | } 133 | QProgressBar::chunk { 134 | background-color: #214037 ; 135 | border-radius: 10px; 136 | } 137 | QMenuBar { 138 | background-color: #151a1e; 139 | } 140 | QMenuBar::item { 141 | color: #d3dae3; 142 | spacing: 3px; 143 | padding: 1px 4px; 144 | background-color: #151a1e; 145 | } 146 | 147 | QMenuBar::item:selected { 148 | background-color: #252a2e; 149 | color: #FFFFFF; 150 | } 151 | QMenu { 152 | background-color: #151a1e; 153 | } 154 | QMenu::item:selected { 155 | background-color: #252a2e; 156 | color: #FFFFFF; 157 | } 158 | QMenu::item { 159 | color: #d3dae3; 160 | background-color: #151a1e; 161 | } 162 | QTabWidget { 163 | color:rgb(0,0,0); 164 | background-color:#000000; 165 | } 166 | QTabWidget::pane { 167 | border-color: #050a0e; 168 | background-color: #1e282c; 169 | border-style: solid; 170 | border-width: 1px; 171 | border-bottom-left-radius: 4px; 172 | border-bottom-right-radius: 4px; 173 | } 174 | QTabBar::tab:first { 175 | border-style: solid; 176 | border-left-width:1px; 177 | border-right-width:0px; 178 | border-top-width:1px; 179 | border-bottom-width:0px; 180 | border-top-color: #050a0e; 181 | border-left-color: #050a0e; 182 | border-bottom-color: #050a0e; 183 | border-top-left-radius: 4px; 184 | color: #d3dae3; 185 | padding: 3px; 186 | margin-left:0px; 187 | background-color: #151a1e; 188 | } 189 | QTabBar::tab:last { 190 | border-style: solid; 191 | border-top-width:1px; 192 | border-left-width:1px; 193 | border-right-width:1px; 194 | border-bottom-width:0px; 195 | border-color: #050a0e; 196 | border-top-right-radius: 4px; 197 | color: #d3dae3; 198 | padding: 3px; 199 | margin-left:0px; 200 | background-color: #151a1e; 201 | } 202 | QTabBar::tab { 203 | border-style: solid; 204 | border-top-width:1px; 205 | border-bottom-width:0px; 206 | border-left-width:1px; 207 | border-top-color: #050a0e; 208 | border-left-color: #050a0e; 209 | border-bottom-color: #050a0e; 210 | color: #d3dae3; 211 | padding: 3px; 212 | margin-left:0px; 213 | background-color: #151a1e; 214 | } 215 | QTabBar::tab:selected, QTabBar::tab:last:selected, QTabBar::tab:hover { 216 | border-style: solid; 217 | border-left-width:1px; 218 | border-bottom-width:0px; 219 | border-right-color: transparent; 220 | border-top-color: #050a0e; 221 | border-left-color: #050a0e; 222 | border-bottom-color: #050a0e; 223 | color: #FFFFFF; 224 | padding: 3px; 225 | margin-left:0px; 226 | background-color: #1e282c; 227 | } 228 | 229 | QTabBar::tab:selected, QTabBar::tab:first:selected, QTabBar::tab:hover { 230 | border-style: solid; 231 | border-left-width:1px; 232 | border-bottom-width:0px; 233 | border-top-width:1px; 234 | border-right-color: transparent; 235 | border-top-color: #050a0e; 236 | border-left-color: #050a0e; 237 | border-bottom-color: #050a0e; 238 | color: #FFFFFF; 239 | padding: 3px; 240 | margin-left:0px; 241 | background-color: #1e282c; 242 | } 243 | 244 | QCheckBox { 245 | color: #d3dae3; 246 | padding: 2px; 247 | } 248 | QCheckBox:disabled { 249 | color: #808086; 250 | padding: 2px; 251 | } 252 | 253 | QCheckBox:hover { 254 | border-radius:4px; 255 | border-style:solid; 256 | padding-left: 1px; 257 | padding-right: 1px; 258 | padding-bottom: 1px; 259 | padding-top: 1px; 260 | border-width:1px; 261 | border-color: transparent; 262 | } 263 | QCheckBox::indicator:checked { 264 | 265 | height: 10px; 266 | width: 10px; 267 | border-style:solid; 268 | border-width: 1px; 269 | border-color: #4fa08b; 270 | color: #000000; 271 | background-color: qradialgradient(cx:0.4, cy:0.4, radius: 1.5,fx:0, fy:0, stop:0 #1e282c, stop:0.3 #1e282c, stop:0.4 #4fa08b, stop:0.5 #1e282c, stop:1 #1e282c); 272 | } 273 | QCheckBox::indicator:unchecked { 274 | 275 | height: 10px; 276 | width: 10px; 277 | border-style:solid; 278 | border-width: 1px; 279 | border-color: #4fa08b; 280 | color: #000000; 281 | } 282 | QRadioButton { 283 | color: #d3dae3; 284 | padding: 1px; 285 | } 286 | QRadioButton::indicator:checked { 287 | height: 10px; 288 | width: 10px; 289 | border-style:solid; 290 | border-radius:5px; 291 | border-width: 1px; 292 | border-color: #4fa08b; 293 | color: #a9b7c6; 294 | background-color: qradialgradient(cx:0.5, cy:0.5, radius:0.4,fx:0.5, fy:0.5, stop:0 #4fa08b, stop:1 #1e282c); 295 | } 296 | QRadioButton::indicator:!checked { 297 | height: 10px; 298 | width: 10px; 299 | border-style:solid; 300 | border-radius:5px; 301 | border-width: 1px; 302 | border-color: #4fa08b; 303 | color: #a9b7c6; 304 | background-color: transparent; 305 | } 306 | QStatusBar { 307 | color:#027f7f; 308 | } 309 | QSpinBox { 310 | color: #d3dae3; 311 | background-color: #222b2e; 312 | border-width: 1px; 313 | border-style: solid; 314 | border-color: #4fa08b; 315 | } 316 | QDoubleSpinBox { 317 | color: #d3dae3; 318 | background-color: #222b2e; 319 | border-width: 1px; 320 | border-style: solid; 321 | border-color: #4fa08b; 322 | } 323 | QTimeEdit { 324 | color: #d3dae3; 325 | background-color: #222b2e; 326 | border-width: 1px; 327 | border-style: solid; 328 | border-color: #4fa08b; 329 | } 330 | QDateTimeEdit { 331 | color: #d3dae3; 332 | background-color: #222b2e; 333 | border-width: 1px; 334 | border-style: solid; 335 | border-color: #4fa08b; 336 | } 337 | QDateEdit { 338 | color: #d3dae3; 339 | background-color: #222b2e; 340 | border-width: 1px; 341 | border-style: solid; 342 | border-color: #4fa08b; 343 | } 344 | QFontComboBox { 345 | color: #d3dae3; 346 | background-color: #222b2e; 347 | border-width: 1px; 348 | border-style: solid; 349 | border-color: #4fa08b; 350 | } 351 | QComboBox { 352 | color: #d3dae3; 353 | background-color: #222b2e; 354 | border-width: 1px; 355 | border-style: solid; 356 | border-color: #4fa08b; 357 | } 358 | 359 | QDial { 360 | background: #16a085; 361 | } 362 | 363 | QToolBox { 364 | color: #a9b7c6; 365 | background-color: #222b2e; 366 | } 367 | QToolBox::tab { 368 | color: #a9b7c6; 369 | background-color:#222b2e; 370 | } 371 | QToolBox::tab:selected { 372 | color: #FFFFFF; 373 | background-color:#222b2e; 374 | } 375 | QScrollArea { 376 | color: #FFFFFF; 377 | background-color:#222b2e; 378 | } 379 | QSlider::groove:horizontal { 380 | height: 5px; 381 | background-color: #52595d; 382 | } 383 | QSlider::groove:vertical { 384 | width: 5px; 385 | background-color: #52595d; 386 | } 387 | QSlider::handle:horizontal { 388 | background: #1a2224; 389 | border-style: solid; 390 | border-width: 1px; 391 | border-color: rgb(207,207,207); 392 | width: 12px; 393 | margin: -5px 0; 394 | border-radius: 7px; 395 | } 396 | QSlider::handle:vertical { 397 | background: #1a2224; 398 | border-style: solid; 399 | border-width: 1px; 400 | border-color: rgb(207,207,207); 401 | height: 12px; 402 | margin: 0 -5px; 403 | border-radius: 7px; 404 | } 405 | QSlider::add-page:horizontal { 406 | background: #52595d; 407 | } 408 | QSlider::add-page:vertical { 409 | background: #52595d; 410 | } 411 | QSlider::sub-page:horizontal { 412 | background-color: #15433a; 413 | } 414 | QSlider::sub-page:vertical { 415 | background-color: #15433a; 416 | } 417 | QScrollBar:horizontal { 418 | max-height: 10px; 419 | border: 1px transparent grey; 420 | margin: 0px 20px 0px 20px; 421 | background: transparent; 422 | } 423 | QScrollBar:vertical { 424 | max-width: 10px; 425 | border: 1px transparent grey; 426 | margin: 20px 0px 20px 0px; 427 | background: transparent; 428 | } 429 | QScrollBar::handle:horizontal { 430 | background: #52595d; 431 | border-style: transparent; 432 | border-radius: 4px; 433 | min-width: 25px; 434 | } 435 | QScrollBar::handle:horizontal:hover { 436 | background: #58a492; 437 | border-style: transparent; 438 | border-radius: 4px; 439 | min-width: 25px; 440 | } 441 | QScrollBar::handle:vertical { 442 | background: #52595d; 443 | border-style: transparent; 444 | border-radius: 4px; 445 | min-height: 25px; 446 | } 447 | QScrollBar::handle:vertical:hover { 448 | background: #58a492; 449 | border-style: transparent; 450 | border-radius: 4px; 451 | min-height: 25px; 452 | } 453 | QScrollBar::add-line:horizontal { 454 | border: 2px transparent grey; 455 | border-top-right-radius: 4px; 456 | border-bottom-right-radius: 4px; 457 | background: #15433a; 458 | width: 20px; 459 | subcontrol-position: right; 460 | subcontrol-origin: margin; 461 | } 462 | QScrollBar::add-line:horizontal:pressed { 463 | border: 2px transparent grey; 464 | border-top-right-radius: 4px; 465 | border-bottom-right-radius: 4px; 466 | background: rgb(181,181,181); 467 | width: 20px; 468 | subcontrol-position: right; 469 | subcontrol-origin: margin; 470 | } 471 | QScrollBar::add-line:vertical { 472 | border: 2px transparent grey; 473 | border-bottom-left-radius: 4px; 474 | border-bottom-right-radius: 4px; 475 | background: #15433a; 476 | height: 20px; 477 | subcontrol-position: bottom; 478 | subcontrol-origin: margin; 479 | } 480 | QScrollBar::add-line:vertical:pressed { 481 | border: 2px transparent grey; 482 | border-bottom-left-radius: 4px; 483 | border-bottom-right-radius: 4px; 484 | background: rgb(181,181,181); 485 | height: 20px; 486 | subcontrol-position: bottom; 487 | subcontrol-origin: margin; 488 | } 489 | QScrollBar::sub-line:horizontal { 490 | border: 2px transparent grey; 491 | border-top-left-radius: 4px; 492 | border-bottom-left-radius: 4px; 493 | background: #15433a; 494 | width: 20px; 495 | subcontrol-position: left; 496 | subcontrol-origin: margin; 497 | } 498 | QScrollBar::sub-line:horizontal:pressed { 499 | border: 2px transparent grey; 500 | border-top-left-radius: 4px; 501 | border-bottom-left-radius: 4px; 502 | background: rgb(181,181,181); 503 | width: 20px; 504 | subcontrol-position: left; 505 | subcontrol-origin: margin; 506 | } 507 | QScrollBar::sub-line:vertical { 508 | border: 2px transparent grey; 509 | border-top-left-radius: 4px; 510 | border-top-right-radius: 4px; 511 | background: #15433a; 512 | height: 20px; 513 | subcontrol-position: top; 514 | subcontrol-origin: margin; 515 | } 516 | QScrollBar::sub-line:vertical:pressed { 517 | border: 2px transparent grey; 518 | border-top-left-radius: 4px; 519 | border-top-right-radius: 4px; 520 | background: rgb(181,181,181); 521 | height: 20px; 522 | subcontrol-position: top; 523 | subcontrol-origin: margin; 524 | } 525 | 526 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { 527 | background: none; 528 | } 529 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { 530 | background: none; 531 | } 532 | -------------------------------------------------------------------------------- /assets/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/assets/ai.png -------------------------------------------------------------------------------- /assets/carmera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/assets/carmera.png -------------------------------------------------------------------------------- /assets/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/assets/lena.png -------------------------------------------------------------------------------- /assets/nanodet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/assets/nanodet.png -------------------------------------------------------------------------------- /assets/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/assets/picture.png -------------------------------------------------------------------------------- /docs/2022-02-04_105740.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_105740.png -------------------------------------------------------------------------------- /docs/2022-02-04_120855.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_120855.png -------------------------------------------------------------------------------- /docs/2022-02-04_121504.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_121504.png -------------------------------------------------------------------------------- /docs/2022-02-04_144250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_144250.png -------------------------------------------------------------------------------- /docs/2022-02-04_150548.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_150548.png -------------------------------------------------------------------------------- /docs/2022-02-04_150705.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/2022-02-04_150705.png -------------------------------------------------------------------------------- /docs/Screenrecorder-2022-02-04-01-10-30-199.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/Screenrecorder-2022-02-04-01-10-30-199.mp4 -------------------------------------------------------------------------------- /docs/Screenshot_2022-02-04-01-13-52-097_org.qtproject.example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/Screenshot_2022-02-04-01-13-52-097_org.qtproject.example.png -------------------------------------------------------------------------------- /docs/Screenshot_2022-02-04-01-14-27-804_org.qtproject.example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/Screenshot_2022-02-04-01-14-27-804_org.qtproject.example.png -------------------------------------------------------------------------------- /docs/Screenshot_2022-02-04-01-15-22-439_org.qtproject.example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/Screenshot_2022-02-04-01-15-22-439_org.qtproject.example.png -------------------------------------------------------------------------------- /docs/bookmarks_ncnn.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | QT+NCNN BookMark 7 |

QT+NCNN

8 |

9 |

书签栏

10 |

11 |

QT+NCNN

12 |

13 |

Qt下载(多种下载通道+所有版本) 14 |
(36条消息) QT下设置android应用图标和名字的方法_这个腿特别长的博客-CSDN博客 15 |
(36条消息) qt for android + opencv的配置及使用_u012230798的博客-CSDN博客 16 |
(GO_GTD_1)基于OpenCV和QT,建立Android图像处理程序 - jsxyhelu - 博客园 17 |
搭建Android+QT+OpenCV环境,实现“单色图片着色”效果 - jsxyhelu - 博客园 18 |
(36条消息) Qt for Android 调用系统摄像头和相册_波风水门-CSDN博客 19 |
Qt调用Android相册获取图片 - 简书 20 |
QtAndroidGallery/mainwindow.cpp · Whu-wxy/Qt-Android-Gallery - 码云 - 开源中国 21 |
(36条消息) Qt Android打开系统相机和相册,获得图片路径_街道口扛把子的博客-CSDN博客 22 |
(36条消息) Qt for Android 程序实现对手机文件的导入打开与导出保存_zhaoyong61088591的博客-CSDN博客 23 |
ANDROID图像处理QT+OpenCV_哔哩哔哩_bilibili 24 |
(36条消息) Qt 实现android camera摄像头的preview和拍照_不解不惑-CSDN博客 25 |
(36条消息) Qt for Android 程序实现对华为mate30手机文件的导入打开_zhaoyong61088591的博客-CSDN博客 26 |
dragonfly1208/QtAndroidProjects at AndroidFileManager 27 |
Qt for Android (二) Qt打开android的相册 - 鬼谷子com - 博客园 28 |
(36条消息) Qt for Android 程序实现对华为mate30手机文件的导入打开_zhaoyong61088591的博客-CSDN博客 29 |
Qt on Android : Working example of a splash screen | Qt Forum 30 |
(36条消息) 如何用Qt/C++访问Android摄像头_anticevc的专栏-CSDN博客_android c++调用摄像头 31 |
Qt-Android-Gallery: Qt on android ,open your album,select a picture and return it. 32 |
Qt ncnn Android部署模型记录 - 知乎 33 |
(36条消息) ncnn + window10 + opencv环境配置 + VS2015_wohaiyo的博客-CSDN博客 34 |
(36条消息) 【ncnn系列一】Win10 + protobuf3.4.0 + NCNN + VS2017 + OpenCV3.4.2 编译和测试_scut_lrr的博客-CSDN博客 35 |
(36条消息) 404 36 |
(36条消息) Qt ncnn Android部署模型记录_街道口扛把子的博客-CSDN博客 37 |
(36条消息) YOLOX (pytorch)模型 转 ONNX 转 ncnn 之❤️C++运行推理❤️【YOLOX 实战三】_专注于AI领域前沿技术学习与分享、略懂实战、学术菜鸟、日常审稿-CSDN博客_yolox 转onnx 38 |
(36条消息) (一)ncnn | Windows(VS2019)编译_Silence_Zzz的博客-CSDN博客_windows 编译ncnn 39 |
(36条消息) 严重性代码说明项目文件行禁止显示状态错误 C4996 'sprintf': This function or variable may be unsafe._唐小先森CAT-CSDN博客 40 |
(36条消息) pc_win10_x64安装ncnn,并使用vulkan_kai1001的专栏-CSDN博客_ncnn vulkan 41 |
开启customerlayer以后 build failed · Issue #52 · cmdbug/YOLOv5_NCNN 42 |
error: undefined symbol: typeinfo for ncnn::Layer >>> did you mean: vtable for ncnn::Layer · Issue #2694 · Tencent/ncnn 43 |
(36条消息) 【爬坑记录】ncnn移植到Android上出现的编译问题_Binbin_Sun的博客-CSDN博客 44 |
ncnn/faq.md at master · Tencent/ncnn 45 |
(36条消息) 7、在Android Studio中调用腾讯开源框架NCNN去实现Yolo-fastest(CPU+GPU)_sxj731533730-CSDN博客 46 |
(36条消息) ncnn的环境搭建和sample运行--ncnn-android-styletransfer(ncnn android, ncnn windows)_维民所止1226的博客-CSDN博客_ncnn环境搭建 47 |

48 |

49 |

50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/vs2019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/vs2019.png -------------------------------------------------------------------------------- /docs/新建文件夹/2022-02-04_143556.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/新建文件夹/2022-02-04_143556.png -------------------------------------------------------------------------------- /docs/新建文件夹/2022-02-04_144010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/新建文件夹/2022-02-04_144010.png -------------------------------------------------------------------------------- /docs/新建文件夹/2022-02-04_144117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/docs/新建文件夹/2022-02-04_144117.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mymainwindow.h" 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | 10 | // 加载QSS 11 | //QFile qss_(":/pic/assets/NeonButtons.qss"); 12 | QFile qss_(":/pic/assets/ManjaroMix.qss"); 13 | if( qss_.open(QFile::ReadOnly)){ 14 | qDebug("open success"); 15 | QString style = QLatin1String(qss_.readAll()); 16 | a.setStyleSheet(style); 17 | qss_.close(); 18 | } 19 | else{ 20 | qDebug("Open failed"); 21 | } 22 | 23 | 24 | MyMainWindow w; 25 | w.show(); 26 | return a.exec(); 27 | } 28 | -------------------------------------------------------------------------------- /model/nanodet_m.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/model/nanodet_m.bin -------------------------------------------------------------------------------- /model/nanodet_m.param: -------------------------------------------------------------------------------- 1 | 7767517 2 | 153 178 3 | Input input.1 0 1 input.1 4 | Convolution Conv_0 1 1 input.1 424 0=24 1=3 3=2 4=1 5=1 6=648 9=2 -23310=1,1.000000e-01 5 | Pooling MaxPool_3 1 1 424 425 1=3 2=2 3=1 5=1 6 | Split splitncnn_0 1 2 425 425_splitncnn_0 425_splitncnn_1 7 | ConvolutionDepthWise Conv_4 1 1 425_splitncnn_1 427 0=24 1=3 3=2 4=1 5=1 6=216 7=24 8 | Convolution Conv_6 1 1 427 430 0=58 1=1 5=1 6=1392 9=2 -23310=1,1.000000e-01 9 | Convolution Conv_9 1 1 425_splitncnn_0 433 0=58 1=1 5=1 6=1392 9=2 -23310=1,1.000000e-01 10 | ConvolutionDepthWise Conv_12 1 1 433 435 0=58 1=3 3=2 4=1 5=1 6=522 7=58 11 | Convolution Conv_14 1 1 435 438 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 12 | Concat Concat_17 2 1 430 438 439 13 | ShuffleChannel Reshape_22 1 1 439 444 0=2 14 | Slice Split_23 1 2 444 445 446 -23300=2,58,-233 15 | Convolution Conv_24 1 1 446 449 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 16 | ConvolutionDepthWise Conv_27 1 1 449 451 0=58 1=3 4=1 5=1 6=522 7=58 17 | Convolution Conv_29 1 1 451 454 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 18 | Concat Concat_32 2 1 445 454 455 19 | ShuffleChannel Reshape_37 1 1 455 460 0=2 20 | Slice Split_38 1 2 460 461 462 -23300=2,58,-233 21 | Convolution Conv_39 1 1 462 465 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 22 | ConvolutionDepthWise Conv_42 1 1 465 467 0=58 1=3 4=1 5=1 6=522 7=58 23 | Convolution Conv_44 1 1 467 470 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 24 | Concat Concat_47 2 1 461 470 471 25 | ShuffleChannel Reshape_52 1 1 471 476 0=2 26 | Slice Split_53 1 2 476 477 478 -23300=2,58,-233 27 | Convolution Conv_54 1 1 478 481 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 28 | ConvolutionDepthWise Conv_57 1 1 481 483 0=58 1=3 4=1 5=1 6=522 7=58 29 | Convolution Conv_59 1 1 483 486 0=58 1=1 5=1 6=3364 9=2 -23310=1,1.000000e-01 30 | Concat Concat_62 2 1 477 486 487 31 | ShuffleChannel Reshape_67 1 1 487 492 0=2 32 | Split splitncnn_1 1 3 492 492_splitncnn_0 492_splitncnn_1 492_splitncnn_2 33 | ConvolutionDepthWise Conv_68 1 1 492_splitncnn_2 494 0=116 1=3 3=2 4=1 5=1 6=1044 7=116 34 | Convolution Conv_70 1 1 494 497 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 35 | Convolution Conv_73 1 1 492_splitncnn_1 500 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 36 | ConvolutionDepthWise Conv_76 1 1 500 502 0=116 1=3 3=2 4=1 5=1 6=1044 7=116 37 | Convolution Conv_78 1 1 502 505 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 38 | Concat Concat_81 2 1 497 505 506 39 | ShuffleChannel Reshape_86 1 1 506 511 0=2 40 | Slice Split_87 1 2 511 512 513 -23300=2,116,-233 41 | Convolution Conv_88 1 1 513 516 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 42 | ConvolutionDepthWise Conv_91 1 1 516 518 0=116 1=3 4=1 5=1 6=1044 7=116 43 | Convolution Conv_93 1 1 518 521 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 44 | Concat Concat_96 2 1 512 521 522 45 | ShuffleChannel Reshape_101 1 1 522 527 0=2 46 | Slice Split_102 1 2 527 528 529 -23300=2,116,-233 47 | Convolution Conv_103 1 1 529 532 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 48 | ConvolutionDepthWise Conv_106 1 1 532 534 0=116 1=3 4=1 5=1 6=1044 7=116 49 | Convolution Conv_108 1 1 534 537 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 50 | Concat Concat_111 2 1 528 537 538 51 | ShuffleChannel Reshape_116 1 1 538 543 0=2 52 | Slice Split_117 1 2 543 544 545 -23300=2,116,-233 53 | Convolution Conv_118 1 1 545 548 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 54 | ConvolutionDepthWise Conv_121 1 1 548 550 0=116 1=3 4=1 5=1 6=1044 7=116 55 | Convolution Conv_123 1 1 550 553 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 56 | Concat Concat_126 2 1 544 553 554 57 | ShuffleChannel Reshape_131 1 1 554 559 0=2 58 | Slice Split_132 1 2 559 560 561 -23300=2,116,-233 59 | Convolution Conv_133 1 1 561 564 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 60 | ConvolutionDepthWise Conv_136 1 1 564 566 0=116 1=3 4=1 5=1 6=1044 7=116 61 | Convolution Conv_138 1 1 566 569 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 62 | Concat Concat_141 2 1 560 569 570 63 | ShuffleChannel Reshape_146 1 1 570 575 0=2 64 | Slice Split_147 1 2 575 576 577 -23300=2,116,-233 65 | Convolution Conv_148 1 1 577 580 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 66 | ConvolutionDepthWise Conv_151 1 1 580 582 0=116 1=3 4=1 5=1 6=1044 7=116 67 | Convolution Conv_153 1 1 582 585 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 68 | Concat Concat_156 2 1 576 585 586 69 | ShuffleChannel Reshape_161 1 1 586 591 0=2 70 | Slice Split_162 1 2 591 592 593 -23300=2,116,-233 71 | Convolution Conv_163 1 1 593 596 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 72 | ConvolutionDepthWise Conv_166 1 1 596 598 0=116 1=3 4=1 5=1 6=1044 7=116 73 | Convolution Conv_168 1 1 598 601 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 74 | Concat Concat_171 2 1 592 601 602 75 | ShuffleChannel Reshape_176 1 1 602 607 0=2 76 | Slice Split_177 1 2 607 608 609 -23300=2,116,-233 77 | Convolution Conv_178 1 1 609 612 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 78 | ConvolutionDepthWise Conv_181 1 1 612 614 0=116 1=3 4=1 5=1 6=1044 7=116 79 | Convolution Conv_183 1 1 614 617 0=116 1=1 5=1 6=13456 9=2 -23310=1,1.000000e-01 80 | Concat Concat_186 2 1 608 617 618 81 | ShuffleChannel Reshape_191 1 1 618 623 0=2 82 | Split splitncnn_2 1 3 623 623_splitncnn_0 623_splitncnn_1 623_splitncnn_2 83 | ConvolutionDepthWise Conv_192 1 1 623_splitncnn_2 625 0=232 1=3 3=2 4=1 5=1 6=2088 7=232 84 | Convolution Conv_194 1 1 625 628 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 85 | Convolution Conv_197 1 1 623_splitncnn_1 631 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 86 | ConvolutionDepthWise Conv_200 1 1 631 633 0=232 1=3 3=2 4=1 5=1 6=2088 7=232 87 | Convolution Conv_202 1 1 633 636 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 88 | Concat Concat_205 2 1 628 636 637 89 | ShuffleChannel Reshape_210 1 1 637 642 0=2 90 | Slice Split_211 1 2 642 643 644 -23300=2,232,-233 91 | Convolution Conv_212 1 1 644 647 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 92 | ConvolutionDepthWise Conv_215 1 1 647 649 0=232 1=3 4=1 5=1 6=2088 7=232 93 | Convolution Conv_217 1 1 649 652 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 94 | Concat Concat_220 2 1 643 652 653 95 | ShuffleChannel Reshape_225 1 1 653 658 0=2 96 | Slice Split_226 1 2 658 659 660 -23300=2,232,-233 97 | Convolution Conv_227 1 1 660 663 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 98 | ConvolutionDepthWise Conv_230 1 1 663 665 0=232 1=3 4=1 5=1 6=2088 7=232 99 | Convolution Conv_232 1 1 665 668 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 100 | Concat Concat_235 2 1 659 668 669 101 | ShuffleChannel Reshape_240 1 1 669 674 0=2 102 | Slice Split_241 1 2 674 675 676 -23300=2,232,-233 103 | Convolution Conv_242 1 1 676 679 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 104 | ConvolutionDepthWise Conv_245 1 1 679 681 0=232 1=3 4=1 5=1 6=2088 7=232 105 | Convolution Conv_247 1 1 681 684 0=232 1=1 5=1 6=53824 9=2 -23310=1,1.000000e-01 106 | Concat Concat_250 2 1 675 684 685 107 | ShuffleChannel Reshape_255 1 1 685 690 0=2 108 | Convolution Conv_256 1 1 492_splitncnn_0 691 0=96 1=1 5=1 6=11136 109 | Convolution Conv_257 1 1 623_splitncnn_0 692 0=96 1=1 5=1 6=22272 110 | Convolution Conv_258 1 1 690 693 0=96 1=1 5=1 6=44544 111 | Split splitncnn_3 1 2 693 693_splitncnn_0 693_splitncnn_1 112 | Interp Resize_277 1 1 693_splitncnn_1 712 0=2 1=2.0 2=2.0 113 | BinaryOp Add_278 2 1 692 712 713 114 | Split splitncnn_4 1 2 713 713_splitncnn_0 713_splitncnn_1 115 | Interp Resize_297 1 1 713_splitncnn_1 732 0=2 1=2.0 2=2.0 116 | BinaryOp Add_298 2 1 691 732 733 117 | Split splitncnn_5 1 2 733 733_splitncnn_0 733_splitncnn_1 118 | Interp Resize_317 1 1 733_splitncnn_1 752 0=2 1=0.5 2=0.5 119 | BinaryOp Add_318 2 1 713_splitncnn_0 752 753 120 | Split splitncnn_6 1 2 753 753_splitncnn_0 753_splitncnn_1 121 | Interp Resize_337 1 1 753_splitncnn_1 772 0=2 1=0.5 2=0.5 122 | BinaryOp Add_338 2 1 693_splitncnn_0 772 773 123 | ConvolutionDepthWise Conv_339 1 1 733_splitncnn_0 776 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 124 | Convolution Conv_342 1 1 776 779 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 125 | ConvolutionDepthWise Conv_345 1 1 779 782 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 126 | Convolution Conv_348 1 1 782 785 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 127 | Convolution Conv_351 1 1 785 786 0=112 1=1 5=1 6=10752 128 | Slice Split_352 1 2 786 787 788 -23300=2,80,-233 129 | Sigmoid Sigmoid_353 1 1 787 789 130 | Reshape Reshape_355 1 1 789 791 0=-1 1=80 131 | Permute Transpose_356 1 1 791 792 0=1 132 | Reshape Reshape_358 1 1 788 794 0=-1 1=32 133 | Permute Transpose_359 1 1 794 795 0=1 134 | ConvolutionDepthWise Conv_360 1 1 753_splitncnn_0 798 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 135 | Convolution Conv_363 1 1 798 801 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 136 | ConvolutionDepthWise Conv_366 1 1 801 804 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 137 | Convolution Conv_369 1 1 804 807 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 138 | Convolution Conv_372 1 1 807 808 0=112 1=1 5=1 6=10752 139 | Slice Split_373 1 2 808 809 810 -23300=2,80,-233 140 | Sigmoid Sigmoid_374 1 1 809 811 141 | Reshape Reshape_376 1 1 811 813 0=-1 1=80 142 | Permute Transpose_377 1 1 813 814 0=1 143 | Reshape Reshape_379 1 1 810 816 0=-1 1=32 144 | Permute Transpose_380 1 1 816 817 0=1 145 | ConvolutionDepthWise Conv_381 1 1 773 820 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 146 | Convolution Conv_384 1 1 820 823 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 147 | ConvolutionDepthWise Conv_387 1 1 823 826 0=96 1=3 4=1 5=1 6=864 7=96 9=2 -23310=1,1.000000e-01 148 | Convolution Conv_390 1 1 826 829 0=96 1=1 5=1 6=9216 9=2 -23310=1,1.000000e-01 149 | Convolution Conv_393 1 1 829 830 0=112 1=1 5=1 6=10752 150 | Slice Split_394 1 2 830 831 832 -23300=2,80,-233 151 | Sigmoid Sigmoid_395 1 1 831 833 152 | Reshape Reshape_397 1 1 833 835 0=-1 1=80 153 | Permute Transpose_398 1 1 835 836 0=1 154 | Reshape Reshape_400 1 1 832 838 0=-1 1=32 155 | Permute Transpose_401 1 1 838 839 0=1 156 | -------------------------------------------------------------------------------- /mymainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mymainwindow.h" 2 | #include "ui_mymainwindow.h" 3 | #include 4 | #include 5 | #include 6 | 7 | //#include 8 | #include 9 | //#include 10 | #include 11 | 12 | #include "layer.h" 13 | #include "net.h" 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | //随机生成BGR颜色 22 | 23 | std::vector getRandomColor(){ 24 | std::vector color; 25 | srand((int)time(0)); // 产生随机种子 把0换成NULL也行 26 | for (int i = 0; i < 3; i++) 27 | { 28 | int temp_color = rand()%256; 29 | color.push_back(temp_color); 30 | 31 | } 32 | 33 | return color; 34 | } 35 | 36 | // ncnn nanodet 37 | struct Object 38 | { 39 | cv::Rect_ rect; 40 | int label; 41 | float prob; 42 | }; 43 | 44 | static inline float intersection_area(const Object& a, const Object& b) 45 | { 46 | cv::Rect_ inter = a.rect & b.rect; 47 | return inter.area(); 48 | } 49 | 50 | static void qsort_descent_inplace(std::vector& faceobjects, int left, int right) 51 | { 52 | int i = left; 53 | int j = right; 54 | float p = faceobjects[(left + right) / 2].prob; 55 | 56 | while (i <= j) 57 | { 58 | while (faceobjects[i].prob > p) 59 | i++; 60 | 61 | while (faceobjects[j].prob < p) 62 | j--; 63 | 64 | if (i <= j) 65 | { 66 | // swap 67 | std::swap(faceobjects[i], faceobjects[j]); 68 | 69 | i++; 70 | j--; 71 | } 72 | } 73 | 74 | #pragma omp parallel sections 75 | { 76 | #pragma omp section 77 | { 78 | if (left < j) qsort_descent_inplace(faceobjects, left, j); 79 | } 80 | #pragma omp section 81 | { 82 | if (i < right) qsort_descent_inplace(faceobjects, i, right); 83 | } 84 | } 85 | } 86 | 87 | static void qsort_descent_inplace(std::vector& faceobjects) 88 | { 89 | if (faceobjects.empty()) 90 | return; 91 | 92 | qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1); 93 | } 94 | 95 | static void nms_sorted_bboxes(const std::vector& faceobjects, std::vector& picked, float nms_threshold) 96 | { 97 | picked.clear(); 98 | 99 | const int n = faceobjects.size(); 100 | 101 | std::vector areas(n); 102 | for (int i = 0; i < n; i++) 103 | { 104 | areas[i] = faceobjects[i].rect.width * faceobjects[i].rect.height; 105 | } 106 | 107 | for (int i = 0; i < n; i++) 108 | { 109 | const Object& a = faceobjects[i]; 110 | 111 | int keep = 1; 112 | for (int j = 0; j < (int)picked.size(); j++) 113 | { 114 | const Object& b = faceobjects[picked[j]]; 115 | 116 | // intersection over union 117 | float inter_area = intersection_area(a, b); 118 | float union_area = areas[i] + areas[picked[j]] - inter_area; 119 | // float IoU = inter_area / union_area 120 | if (inter_area / union_area > nms_threshold) 121 | keep = 0; 122 | } 123 | 124 | if (keep) 125 | picked.push_back(i); 126 | } 127 | } 128 | 129 | static void generate_proposals(const ncnn::Mat& cls_pred, const ncnn::Mat& dis_pred, int stride, const ncnn::Mat& in_pad, float prob_threshold, std::vector& objects) 130 | { 131 | const int num_grid = cls_pred.h; 132 | 133 | int num_grid_x; 134 | int num_grid_y; 135 | if (in_pad.w > in_pad.h) 136 | { 137 | num_grid_x = in_pad.w / stride; 138 | num_grid_y = num_grid / num_grid_x; 139 | } 140 | else 141 | { 142 | num_grid_y = in_pad.h / stride; 143 | num_grid_x = num_grid / num_grid_y; 144 | } 145 | 146 | const int num_class = cls_pred.w; 147 | const int reg_max_1 = dis_pred.w / 4; 148 | 149 | for (int i = 0; i < num_grid_y; i++) 150 | { 151 | for (int j = 0; j < num_grid_x; j++) 152 | { 153 | const int idx = i * num_grid_x + j; 154 | 155 | const float* scores = cls_pred.row(idx); 156 | 157 | // find label with max score 158 | int label = -1; 159 | float score = -FLT_MAX; 160 | for (int k = 0; k < num_class; k++) 161 | { 162 | if (scores[k] > score) 163 | { 164 | label = k; 165 | score = scores[k]; 166 | } 167 | } 168 | 169 | if (score >= prob_threshold) 170 | { 171 | ncnn::Mat bbox_pred(reg_max_1, 4, (void*)dis_pred.row(idx)); 172 | { 173 | ncnn::Layer* softmax = ncnn::create_layer("Softmax"); 174 | 175 | ncnn::ParamDict pd; 176 | pd.set(0, 1); // axis 177 | pd.set(1, 1); 178 | softmax->load_param(pd); 179 | 180 | ncnn::Option opt; 181 | opt.num_threads = 1; 182 | opt.use_packing_layout = false; 183 | 184 | softmax->create_pipeline(opt); 185 | 186 | softmax->forward_inplace(bbox_pred, opt); 187 | 188 | softmax->destroy_pipeline(opt); 189 | 190 | delete softmax; 191 | } 192 | 193 | float pred_ltrb[4]; 194 | for (int k = 0; k < 4; k++) 195 | { 196 | float dis = 0.f; 197 | const float* dis_after_sm = bbox_pred.row(k); 198 | for (int l = 0; l < reg_max_1; l++) 199 | { 200 | dis += l * dis_after_sm[l]; 201 | } 202 | 203 | pred_ltrb[k] = dis * stride; 204 | } 205 | 206 | float pb_cx = (j + 0.5f) * stride; 207 | float pb_cy = (i + 0.5f) * stride; 208 | 209 | float x0 = pb_cx - pred_ltrb[0]; 210 | float y0 = pb_cy - pred_ltrb[1]; 211 | float x1 = pb_cx + pred_ltrb[2]; 212 | float y1 = pb_cy + pred_ltrb[3]; 213 | 214 | Object obj; 215 | obj.rect.x = x0; 216 | obj.rect.y = y0; 217 | obj.rect.width = x1 - x0; 218 | obj.rect.height = y1 - y0; 219 | obj.label = label; 220 | obj.prob = score; 221 | 222 | objects.push_back(obj); 223 | } 224 | } 225 | } 226 | } 227 | 228 | static int detect_nanodet(const cv::Mat& bgr, std::vector& objects) 229 | { 230 | ncnn::Net nanodet; 231 | 232 | nanodet.opt.use_vulkan_compute = true; 233 | // nanodet.opt.use_bf16_storage = true; 234 | 235 | // original pretrained model from https://github.com/RangiLyu/nanodet 236 | // the ncnn model https://github.com/nihui/ncnn-assets/tree/master/models 237 | 238 | QFile::copy("assets:/pic/nanodet_m.param", "nanodet_m.param"); 239 | QFile::copy("assets:/pic/nanodet_m.bin", "nanodet_m.bin"); 240 | nanodet.load_param("nanodet_m.param"); 241 | nanodet.load_model("nanodet_m.bin"); 242 | 243 | int width = bgr.cols; 244 | int height = bgr.rows; 245 | 246 | const int target_size = 320; 247 | const float prob_threshold = 0.4f; 248 | const float nms_threshold = 0.5f; 249 | 250 | // pad to multiple of 32 251 | int w = width; 252 | int h = height; 253 | float scale = 1.f; 254 | if (w > h) 255 | { 256 | scale = (float)target_size / w; 257 | w = target_size; 258 | h = h * scale; 259 | } 260 | else 261 | { 262 | scale = (float)target_size / h; 263 | h = target_size; 264 | w = w * scale; 265 | } 266 | 267 | ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR, width, height, w, h); 268 | 269 | // pad to target_size rectangle 270 | int wpad = (w + 31) / 32 * 32 - w; 271 | int hpad = (h + 31) / 32 * 32 - h; 272 | ncnn::Mat in_pad; 273 | ncnn::copy_make_border(in, in_pad, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, ncnn::BORDER_CONSTANT, 0.f); 274 | 275 | const float mean_vals[3] = {103.53f, 116.28f, 123.675f}; 276 | const float norm_vals[3] = {0.017429f, 0.017507f, 0.017125f}; 277 | in_pad.substract_mean_normalize(mean_vals, norm_vals); 278 | 279 | ncnn::Extractor ex = nanodet.create_extractor(); 280 | 281 | ex.input("input.1", in_pad); 282 | 283 | std::vector proposals; 284 | 285 | // stride 8 286 | { 287 | ncnn::Mat cls_pred; 288 | ncnn::Mat dis_pred; 289 | ex.extract("792", cls_pred); 290 | ex.extract("795", dis_pred); 291 | 292 | std::vector objects8; 293 | generate_proposals(cls_pred, dis_pred, 8, in_pad, prob_threshold, objects8); 294 | 295 | proposals.insert(proposals.end(), objects8.begin(), objects8.end()); 296 | } 297 | 298 | // stride 16 299 | { 300 | ncnn::Mat cls_pred; 301 | ncnn::Mat dis_pred; 302 | ex.extract("814", cls_pred); 303 | ex.extract("817", dis_pred); 304 | 305 | std::vector objects16; 306 | generate_proposals(cls_pred, dis_pred, 16, in_pad, prob_threshold, objects16); 307 | 308 | proposals.insert(proposals.end(), objects16.begin(), objects16.end()); 309 | } 310 | 311 | // stride 32 312 | { 313 | ncnn::Mat cls_pred; 314 | ncnn::Mat dis_pred; 315 | ex.extract("836", cls_pred); 316 | ex.extract("839", dis_pred); 317 | 318 | std::vector objects32; 319 | generate_proposals(cls_pred, dis_pred, 32, in_pad, prob_threshold, objects32); 320 | 321 | proposals.insert(proposals.end(), objects32.begin(), objects32.end()); 322 | } 323 | 324 | // sort all proposals by score from highest to lowest 325 | qsort_descent_inplace(proposals); 326 | 327 | // apply nms with nms_threshold 328 | std::vector picked; 329 | nms_sorted_bboxes(proposals, picked, nms_threshold); 330 | 331 | int count = picked.size(); 332 | 333 | objects.resize(count); 334 | for (int i = 0; i < count; i++) 335 | { 336 | objects[i] = proposals[picked[i]]; 337 | 338 | // adjust offset to original unpadded 339 | float x0 = (objects[i].rect.x - (wpad / 2)) / scale; 340 | float y0 = (objects[i].rect.y - (hpad / 2)) / scale; 341 | float x1 = (objects[i].rect.x + objects[i].rect.width - (wpad / 2)) / scale; 342 | float y1 = (objects[i].rect.y + objects[i].rect.height - (hpad / 2)) / scale; 343 | 344 | // clip 345 | x0 = std::max(std::min(x0, (float)(width - 1)), 0.f); 346 | y0 = std::max(std::min(y0, (float)(height - 1)), 0.f); 347 | x1 = std::max(std::min(x1, (float)(width - 1)), 0.f); 348 | y1 = std::max(std::min(y1, (float)(height - 1)), 0.f); 349 | 350 | objects[i].rect.x = x0; 351 | objects[i].rect.y = y0; 352 | objects[i].rect.width = x1 - x0; 353 | objects[i].rect.height = y1 - y0; 354 | } 355 | 356 | return 0; 357 | } 358 | 359 | 360 | cv::Mat draw_objects(const cv::Mat& bgr, const std::vector& objects) 361 | { 362 | static const char* class_names[] = { 363 | "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light", 364 | "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", 365 | "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", 366 | "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", 367 | "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple", 368 | "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch", 369 | "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", 370 | "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear", 371 | "hair drier", "toothbrush" 372 | }; 373 | 374 | cv::Mat image = bgr.clone(); 375 | 376 | for (size_t i = 0; i < objects.size(); i++) 377 | { 378 | std::vector CurColor = getRandomColor(); 379 | const Object& obj = objects[i]; 380 | 381 | fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob, 382 | obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height); 383 | 384 | int tl_ = (int)(0.002*image.rows); 385 | if (tl_ == 0){ 386 | tl_ = 1; 387 | } 388 | cv::rectangle(image, obj.rect, cv::Scalar(CurColor[0], CurColor[1], CurColor[2]),tl_); 389 | 390 | char text[256]; 391 | sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100); 392 | qDebug() << class_names[obj.label] << "," << obj.prob * 100; 393 | 394 | int baseLine = 0; 395 | cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, (float)tl_/2, tl_,&baseLine); 396 | 397 | int x = obj.rect.x; 398 | int y = obj.rect.y - label_size.height - baseLine; 399 | if (y < 0) 400 | y = 0; 401 | if (x + label_size.width > image.cols) 402 | x = image.cols - label_size.width; 403 | 404 | cv::rectangle(image, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)), 405 | cv::Scalar(CurColor[0], CurColor[1], CurColor[2]), -1); 406 | 407 | cv::putText(image, text, cv::Point(x, y + label_size.height), 408 | cv::FONT_HERSHEY_SIMPLEX, (float)tl_/2, cv::Scalar(0, 0, 0),tl_); 409 | } 410 | 411 | // cv::imshow("image", image); 412 | // cv::waitKey(0); 413 | 414 | return image; 415 | } 416 | 417 | 418 | 419 | 420 | //获取android 相册 421 | QString selectedFileName; 422 | cv::Mat Img2Det; 423 | 424 | #ifdef __cplusplus 425 | extern "C" { 426 | #endif 427 | 428 | JNIEXPORT void JNICALL 429 | Java_com_amin_QtAndroidGallery_QtAndroidGallery_fileSelected(JNIEnv */*env*/, 430 | jobject /*obj*/, 431 | jstring results) 432 | { 433 | selectedFileName = QAndroidJniObject(results).toString(); 434 | } 435 | 436 | #ifdef __cplusplus 437 | } 438 | #endif 439 | 440 | 441 | //label显示Mat 442 | void LabelDisplayMat(QLabel *label, cv::Mat &mat){ 443 | 444 | cv::Mat Rgb; 445 | QImage Img; 446 | int w = label->rect().width(); 447 | int h = label->rect().height(); 448 | 449 | if (mat.channels() == 3){ 450 | cv::cvtColor(mat,Rgb,cv::COLOR_BGR2RGB); 451 | cv::resize(Rgb,Rgb,cv::Size(w,h)); 452 | 453 | Img = QImage((const uchar*)(Rgb.data), Rgb.cols,Rgb.rows,Rgb.cols * Rgb.channels(),QImage::Format_RGB888); 454 | } 455 | else{ 456 | cv::Mat grayImg; 457 | cv::resize(mat,grayImg,cv::Size(w,h)); 458 | Img = QImage((const uchar*)(grayImg.data), grayImg.cols,grayImg.rows,grayImg.cols * grayImg.channels(),QImage::Format_Indexed8); 459 | } 460 | 461 | label->setPixmap(QPixmap::fromImage(Img)); 462 | label->setScaledContents(true); //自适应大小 463 | 464 | } 465 | 466 | 467 | 468 | MyMainWindow::MyMainWindow(QWidget *parent) 469 | : QMainWindow(parent) 470 | , ui(new Ui::MyMainWindow) 471 | { 472 | ui->setupUi(this); 473 | } 474 | 475 | MyMainWindow::~MyMainWindow() 476 | { 477 | delete ui; 478 | } 479 | 480 | 481 | void MyMainWindow::on_pushButton_clicked() 482 | { 483 | 484 | //在android中是不work的 485 | // QString fileName = QFileDialog::getOpenFileName(this, tr("打开图片"), "assets:/pic", tr("Image Files(*.jpg *.png *.bmp *.pgm *.pbm);;All(*.*)")); 486 | // qDebug() << "fileName: " << fileName ; 487 | // QMessageBox::information(NULL, "选择的图片路径", fileName, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); 488 | 489 | selectedFileName = "#"; 490 | QAndroidJniObject::callStaticMethod("com/amin/QtAndroidGallery/QtAndroidGallery", 491 | "openAnImage", 492 | "()V"); 493 | while(selectedFileName == "#") 494 | qApp->processEvents(); 495 | 496 | qDebug()<<"file name:"<label_2->setPixmap(QPixmap::fromImage(img)); 501 | 502 | cv::Mat img = cv::imread(selectedFileName.toStdString()); 503 | LabelDisplayMat(ui->label_2,img); 504 | Img2Det = img.clone(); 505 | } 506 | 507 | 508 | 509 | } 510 | 511 | void MyMainWindow::on_pushButton_2_clicked() 512 | { 513 | // QFile::copy("assets:/pic/ai.png", "ai.png"); 514 | // cv::Mat img = cv::imread("ai.png"); 515 | // LabelDisplayMat(ui->label_2,img); 516 | 517 | selectedFileName = "#"; 518 | QAndroidJniObject::callStaticMethod("com/amin/QtAndroidGallery/QtAndroidGallery", 519 | "captureAnImage", 520 | "()V"); 521 | while(selectedFileName == "#") 522 | qApp->processEvents(); 523 | 524 | if(selectedFileName != "#") 525 | { 526 | if(QFile(selectedFileName).exists()){ 527 | cv::Mat img = cv::imread(selectedFileName.toStdString()); 528 | LabelDisplayMat(ui->label_2,img); 529 | Img2Det = img.clone(); 530 | } 531 | 532 | } 533 | 534 | } 535 | 536 | void MyMainWindow::on_pushButton_3_clicked() 537 | { 538 | // QFile::copy("assets:/pic/bus.jpg", "bus.jpg"); 539 | // cv::Mat m = cv::imread("bus.jpg", 1); 540 | qDebug() << "开始识别"; 541 | 542 | if (!Img2Det.empty()){ 543 | std::vector objects; 544 | detect_nanodet(Img2Det, objects); 545 | 546 | cv::Mat afterImg; 547 | afterImg = draw_objects(Img2Det, objects); 548 | 549 | LabelDisplayMat(ui->label_2,afterImg); 550 | Img2Det.release(); 551 | } 552 | else{ 553 | QMessageBox::information(NULL, "请选择图片", "暂时没有被选中的图片资源!", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); 554 | } 555 | 556 | 557 | } 558 | -------------------------------------------------------------------------------- /mymainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MYMAINWINDOW_H 2 | #define MYMAINWINDOW_H 3 | 4 | #include 5 | #include 6 | 7 | QT_BEGIN_NAMESPACE 8 | namespace Ui { class MyMainWindow; } 9 | QT_END_NAMESPACE 10 | 11 | class MyMainWindow : public QMainWindow 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | MyMainWindow(QWidget *parent = nullptr); 17 | ~MyMainWindow(); 18 | 19 | private slots: 20 | void on_pushButton_clicked(); 21 | 22 | void on_pushButton_2_clicked(); 23 | 24 | void on_pushButton_3_clicked(); 25 | 26 | private: 27 | Ui::MyMainWindow *ui; 28 | }; 29 | #endif // MYMAINWINDOW_H 30 | -------------------------------------------------------------------------------- /mymainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MyMainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 299 10 | 611 11 | 12 | 13 | 14 | MyMainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 281 23 | 31 24 | 25 | 26 | 27 | 28 | 2810 29 | 100 30 | 31 | 32 | 33 | 34 | Agency FB 35 | 20 36 | 50 37 | false 38 | false 39 | 40 | 41 | 42 | font: 9pt "幼圆"; 43 | font: 20pt "Agency FB"; 44 | 45 | 46 | 47 | NanoDet NCNN 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 75 56 | 23 57 | 58 | 59 | 60 | 61 | 750 62 | 100 63 | 64 | 65 | 66 | 67 | Arial 68 | 20 69 | 50 70 | false 71 | false 72 | 73 | 74 | 75 | 76 | font: 20pt "Arial"; 77 | 78 | 79 | 相册 80 | 81 | 82 | 83 | :/pic/assets/picture.png:/pic/assets/picture.png 84 | 85 | 86 | 87 | 64 88 | 64 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 75 98 | 23 99 | 100 | 101 | 102 | 103 | 750 104 | 100 105 | 106 | 107 | 108 | 109 | Arial 110 | 20 111 | 50 112 | false 113 | false 114 | 115 | 116 | 117 | font: 20pt "Arial"; 118 | 119 | 120 | 相机 121 | 122 | 123 | 124 | :/pic/assets/carmera.png:/pic/assets/carmera.png 125 | 126 | 127 | 128 | 64 129 | 64 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 95 139 | 23 140 | 141 | 142 | 143 | 144 | 910 145 | 100 146 | 147 | 148 | 149 | 150 | Arial 151 | 20 152 | 50 153 | false 154 | false 155 | 156 | 157 | 158 | font: 20pt "Arial"; 159 | 160 | 161 | NanoDet 162 | 163 | 164 | 165 | :/pic/assets/ai.png:/pic/assets/ai.png 166 | 167 | 168 | 169 | 64 170 | 64 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 271 180 | 491 181 | 182 | 183 | 184 | 185 | 2710 186 | 4910 187 | 188 | 189 | 190 | image: url(:/pic/assets/nanodet.png); 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 0 203 | 0 204 | 299 205 | 26 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /pic.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | assets/lena.png 4 | assets/carmera.png 5 | assets/picture.png 6 | assets/ai.png 7 | assets/ManjaroMix.qss 8 | assets/nanodet.png 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pic/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/ai.png -------------------------------------------------------------------------------- /pic/bus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/bus.jpg -------------------------------------------------------------------------------- /pic/carmera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/carmera.png -------------------------------------------------------------------------------- /pic/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/lena.png -------------------------------------------------------------------------------- /pic/nanodet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/nanodet.png -------------------------------------------------------------------------------- /pic/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/picture.png -------------------------------------------------------------------------------- /pic/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataXujing/Qt_NCNN_NanoDet/55e18b7b5e08562bf241c4d011c26095e0804ac9/pic/start.png -------------------------------------------------------------------------------- /yoloxncnn.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | QT += androidextras 3 | 4 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 5 | 6 | CONFIG += c++11 7 | 8 | # The following define makes your compiler emit warnings if you use 9 | # any Qt feature that has been marked deprecated (the exact warnings 10 | # depend on your compiler). Please consult the documentation of the 11 | # deprecated API in order to know how to port your code away from it. 12 | DEFINES += QT_DEPRECATED_WARNINGS 13 | 14 | # You can also make your code fail to compile if it uses deprecated APIs. 15 | # In order to do so, uncomment the following line. 16 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 17 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 18 | 19 | SOURCES += \ 20 | main.cpp \ 21 | mymainwindow.cpp 22 | 23 | HEADERS += \ 24 | mymainwindow.h 25 | 26 | FORMS += \ 27 | mymainwindow.ui 28 | 29 | # Default rules for deployment. 30 | qnx: target.path = /tmp/$${TARGET}/bin 31 | else: unix:!android: target.path = /opt/$${TARGET}/bin 32 | !isEmpty(target.path): INSTALLS += target 33 | 34 | RESOURCES += \ 35 | pic.qrc 36 | 37 | DISTFILES += \ 38 | android/AndroidManifest.xml \ 39 | android/build.gradle \ 40 | android/gradle/wrapper/gradle-wrapper.jar \ 41 | android/gradle/wrapper/gradle-wrapper.properties \ 42 | android/gradlew \ 43 | android/gradlew.bat \ 44 | android/res/values/libs.xml \ 45 | android/src/com/amin/QtAndroidGallery/QtAndroidGallery.java \ 46 | model/yolact.bin \ 47 | model/yolact.param 48 | 49 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 50 | 51 | QMAKE_CXXFLAGS += -fopenmp -static-openmp 52 | QMAKE_LFLAGS += -fopenmp -static-openmp 53 | LIBS += -fopenmp -static-openmp 54 | 55 | android { 56 | ANDROID_OPENCV = D:/QT/OpenCV-android-sdk/sdk/native 57 | #ANDROID_OPENCV = D:/NCNN/opencv-mobile-4.5.1-android/sdk/native 58 | INCLUDEPATH += \ 59 | $$ANDROID_OPENCV/jni/include/opencv2 \ 60 | $$ANDROID_OPENCV/jni/include \ 61 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/include \ 62 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/include/ncnn 63 | 64 | 65 | LIBS += \ 66 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_ml.a \ 67 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_objdetect.a \ 68 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_calib3d.a \ 69 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a \ 70 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a \ 71 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a \ 72 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_flann.a \ 73 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a \ 74 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_dnn.a \ 75 | $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a \ 76 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libcpufeatures.a \ 77 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libIlmImf.a \ 78 | #$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjasper.a \ 79 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjpeg-turbo.a \ 80 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibpng.a \ 81 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibprotobuf.a \ 82 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibtiff.a \ 83 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibwebp.a \ 84 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libquirc.a \ 85 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtbb.a \ 86 | $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtegra_hal.a \ 87 | $$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_java4.so \ 88 | D:/NCNN/ncnn-20211208-android/armeabi-v7a/lib/libncnn.a \ 89 | D:/QT/android-ndk-r21/platforms/android-28/arch-arm/usr/lib/libandroid.so \ 90 | D:/QT/android-ndk-r21/toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.8/lib/linux/arm/libomp.a 91 | D:/QT/android-ndk-r21/toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.8/lib/linux/arm/libomp.so 92 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a \ 93 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a \ 94 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a \ 95 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a \ 96 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_photo.a \ 97 | #$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a \ 98 | 99 | # add other file 100 | #data.files += ssd_mobilenet_v1_coco_11_06_2017/frozen_inference_graph.pb 101 | #data.files += ssd_mobilenet_v1_coco_11_06_2017/ssd_mobilenet_v1_coco.pbtxt 102 | 103 | data.files += pic/nanodet.png 104 | data.files += pic/ai.png 105 | data.files += pic/carmera.png 106 | data.files += pic/picture.png 107 | data.files += pic/bus.jpg 108 | data.files += model/nanodet_m.param 109 | data.files += model/nanodet_m.bin 110 | 111 | data.path = /assets/pic 112 | INSTALLS += data 113 | 114 | #QMAKE_CFLAGS += -fno-rtti 115 | #QMAKE_CXXFLAGS += -fno-rtti 116 | 117 | 118 | 119 | } 120 | 121 | ANDROID_EXTRA_LIBS += D:/QT/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_java4.so \ 122 | D:/QT/android-ndk-r21/platforms/android-28/arch-arm/usr/lib/libandroid.so \ 123 | D:/QT/android-ndk-r21/toolchains/llvm/prebuilt/windows-x86_64/lib64/clang/9.0.8/lib/linux/arm/libomp.so 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /yoloxncnn.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {2e7d8320-5d49-49b9-b8c2-682af47d3eec} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | -fno-delayed-template-parsing 60 | 61 | true 62 | 63 | 64 | 65 | ProjectExplorer.Project.Target.0 66 | 67 | Android for armeabi-v7a,arm64-v8a,x86,x86_64 (Clang Qt 5.14.2 for Android) 68 | Android for armeabi-v7a,arm64-v8a,x86,x86_64 (Clang Qt 5.14.2 for Android) 69 | {66c1016c-8ef7-4a66-87d2-e8702d500954} 70 | 1 71 | 0 72 | 0 73 | 74 | D:/QT/project/build-yoloxncnn-Android_for_armeabi_v7a_arm64_v8a_x86_x86_64_Clang_Qt_5_14_2_for_Android-Debug 75 | 76 | 77 | true 78 | QtProjectManager.QMakeBuildStep 79 | true 80 | 81 | false 82 | false 83 | false 84 | 85 | 86 | true 87 | Qt4ProjectManager.MakeStep 88 | 89 | false 90 | 91 | 92 | false 93 | 94 | 95 | true 96 | Qt4ProjectManager.AndroidPackageInstallationStep 97 | 98 | 99 | android-28 100 | 101 | true 102 | QmakeProjectManager.AndroidBuildApkStep 103 | false 104 | false 105 | 106 | 4 107 | Build 108 | Build 109 | ProjectExplorer.BuildSteps.Build 110 | 111 | 112 | 113 | true 114 | Qt4ProjectManager.MakeStep 115 | 116 | true 117 | clean 118 | 119 | false 120 | 121 | 1 122 | Clean 123 | Clean 124 | ProjectExplorer.BuildSteps.Clean 125 | 126 | 2 127 | false 128 | 129 | Debug 130 | Qt4ProjectManager.Qt4BuildConfiguration 131 | 2 132 | 133 | 134 | D:/QT/project/build-yoloxncnn-Android_for_armeabi_v7a_arm64_v8a_x86_x86_64_Clang_Qt_5_14_2_for_Android-Release 135 | 136 | 137 | true 138 | QtProjectManager.QMakeBuildStep 139 | false 140 | 141 | false 142 | false 143 | true 144 | 145 | 146 | true 147 | Qt4ProjectManager.MakeStep 148 | 149 | false 150 | 151 | 152 | false 153 | 154 | 155 | true 156 | Qt4ProjectManager.AndroidPackageInstallationStep 157 | 158 | 159 | android-28 160 | 161 | true 162 | QmakeProjectManager.AndroidBuildApkStep 163 | false 164 | false 165 | 166 | 4 167 | Build 168 | Build 169 | ProjectExplorer.BuildSteps.Build 170 | 171 | 172 | 173 | true 174 | Qt4ProjectManager.MakeStep 175 | 176 | true 177 | clean 178 | 179 | false 180 | 181 | 1 182 | Clean 183 | Clean 184 | ProjectExplorer.BuildSteps.Clean 185 | 186 | 2 187 | false 188 | 189 | Release 190 | Qt4ProjectManager.Qt4BuildConfiguration 191 | 0 192 | 193 | 194 | D:/QT/project/build-yoloxncnn-Android_for_armeabi_v7a_arm64_v8a_x86_x86_64_Clang_Qt_5_14_2_for_Android-Profile 195 | 196 | 197 | true 198 | QtProjectManager.QMakeBuildStep 199 | true 200 | 201 | false 202 | true 203 | true 204 | 205 | 206 | true 207 | Qt4ProjectManager.MakeStep 208 | 209 | false 210 | 211 | 212 | false 213 | 214 | 215 | true 216 | Qt4ProjectManager.AndroidPackageInstallationStep 217 | 218 | 219 | android-28 220 | 221 | true 222 | QmakeProjectManager.AndroidBuildApkStep 223 | false 224 | false 225 | 226 | 4 227 | Build 228 | Build 229 | ProjectExplorer.BuildSteps.Build 230 | 231 | 232 | 233 | true 234 | Qt4ProjectManager.MakeStep 235 | 236 | true 237 | clean 238 | 239 | false 240 | 241 | 1 242 | Clean 243 | Clean 244 | ProjectExplorer.BuildSteps.Clean 245 | 246 | 2 247 | false 248 | 249 | Profile 250 | Qt4ProjectManager.Qt4BuildConfiguration 251 | 0 252 | 253 | 3 254 | 255 | 256 | 257 | true 258 | Qt4ProjectManager.AndroidDeployQtStep 259 | false 260 | 261 | 1 262 | Deploy 263 | Deploy 264 | ProjectExplorer.BuildSteps.Deploy 265 | 266 | 1 267 | Qt4ProjectManager.AndroidDeployConfiguration2 268 | 269 | 1 270 | 271 | 272 | arm64-v8a 273 | armeabi-v7a 274 | armeabi 275 | 276 | de5f2887d62 277 | 22 278 | 279 | 280 | dwarf 281 | 282 | cpu-cycles 283 | 284 | 285 | 250 286 | 287 | -e 288 | cpu-cycles 289 | --call-graph 290 | dwarf,4096 291 | -F 292 | 250 293 | 294 | -F 295 | true 296 | 4096 297 | false 298 | false 299 | 1000 300 | 301 | true 302 | 303 | false 304 | false 305 | false 306 | false 307 | true 308 | 0.01 309 | 10 310 | true 311 | kcachegrind 312 | 1 313 | 25 314 | 315 | 1 316 | true 317 | false 318 | true 319 | valgrind 320 | 321 | 0 322 | 1 323 | 2 324 | 3 325 | 4 326 | 5 327 | 6 328 | 7 329 | 8 330 | 9 331 | 10 332 | 11 333 | 12 334 | 13 335 | 14 336 | 337 | 338 | 339 | 340 | 0 341 | 342 | yoloxncnn 343 | Qt4ProjectManager.AndroidRunConfiguration:D:/QT/project/yoloxncnn/yoloxncnn.pro 344 | D:/QT/project/yoloxncnn/yoloxncnn.pro 345 | 346 | false 347 | 348 | false 349 | true 350 | false 351 | false 352 | true 353 | 354 | 1 355 | 356 | 357 | 358 | ProjectExplorer.Project.TargetCount 359 | 1 360 | 361 | 362 | ProjectExplorer.Project.Updater.FileVersion 363 | 22 364 | 365 | 366 | Version 367 | 22 368 | 369 | 370 | --------------------------------------------------------------------------------