OpenCV是我们大家非常熟悉的图像处理开源类库;在其新版本将原本在Contrib分库中的DNN模块融合到了主库中,并且更新了相应文档。这样我们就能够非常方便地利用OpenCV实现一些属于DeepLearning范畴的效果,比如“超级分辨率”“单色图片着色”“色彩迁移”等。当我们想把软件处理的平台由PC机转移到嵌入式平台和手机上的时候,QT也是能和OpenCV配合地非常好的平台。在这里,我具体研究了如何搭建Android+QT+OpenCV环境,实现“单色图片着色”效果;并将相关内容整理如下,希望能够对有这方面需求的工程师提供帮助。
一、环境配置
        首先我们面临的问题是工具版本的选择,虽然我们已经确定了Android+QT+OpenCV的基本软件结构,但是在每一个环节都需要选择具体的版本。
        Android需要选择的是sdk和ndk的版本,我这里使用的是Android10(API29)+android-ndk-r20的组合,基本上是现在(2019年9月)最新的组合了;
        QT需要选择的是QT和QT Creator,我这里选择的是QT 5.13.1+QT Creator 4.10.0,同样是现在(2019年9月)最新的组合;
        OpenCV用于Android的话,官方有Prebuild版本,我这里采用的是opencv-4.1.0-android-sdk。
 
1、SDK的下载和配置
       首先我们正确安装JDK并且将其目录放入PATH中,而后需要下载android-sdk、android-ndk-r20、OpenCV-android-sdk,并且分别解压放置在非中文无空格的目录中。(下载地址看文末)
 
2、QT的安装和配置
       下载QT在线安装程序直接安装,安装过程中除了默认选中的“Developer and designer Tools”以外,只需选中QT5.13.1下的“Android Armv7”即可。
完成后主要是做一个配置“工具”->"选项“中”设备“栏目"JDK""SDK""NDK"都配置到正确的目录下
这里容易出现各种错误,尽可能保证使用我推荐的软件版本,避免错误影响进度。
此时,你应该就已经可以在Android上运行QT自带的例子。
         任意选择一个例子,比如“Qt 3D: Audio Visualizer Example ”,选择之前配置好的Kits,连接好实体手机或者模拟器(参考文末链接),点击“运行”,稍等一会,即可出现效果。
        这里需要注意,第一次运行可能需要从网络上下载一些东西,所以请保证网络顺畅。
 
3、OpenCV环境的引入
 
       下面我们想办法将OpenCV环境引入进来,之前已经下载了“OpenCV-android-sdk",它的文件目录是这样:
这时,需要我们配置QT项目的.pro文件,最为重要的就是在.pro文件中添加这个模块
 
android {
ANDROID_OPENCV = D:/OpenCV-android-sdk/sdk/native
INCLUDEPATH += \
$$ANDROID_OPENCV/jni/include/opencv2 \
$$ANDROID_OPENCV/jni/include \

LIBS += \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_ml.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_objdetect.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_calib3d.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_flann.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_dnn.a \
$$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libcpufeatures.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libIlmImf.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjasper.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjpeg-turbo.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibpng.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibprotobuf.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibtiff.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibwebp.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libquirc.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtbb.a \
$$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtegra_hal.a \
$$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_java4.so

}

 
这里就是告诉QT到哪里去寻找OpenCV-android-sdk的include文件和libs文件,最后,还需要将libopencv_java4.so添加到项目中
 
 
 
方法是对于当前项目,点击“项目”->“详情”->"add"将这个libopencv_java4.so加进去,需要注意这里有bug,添加完成后,需要手动修
 
改.pro文件这个部分至正确:
 
 
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_EXTRA_LIBS = \
D:/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_java4.so
 
4、DNN模型的引入
      
      由于所有的DNN模型都需要调用模型文件(.pb等),而这些文件都必须预先编译到APK中去。使用 Qt 如何来做了?还是在.pro文
件上下功夫。
 
      打开 Qt 工程文件pro,并添加如下代码
 
data.files += images/*.*
data.files += dnn/*.prototxt
data.files += dnn/*.caffemodel
data.path = /assets/dnn
INSTALLS += data
 
 
注意,这里只是我的示例写法,images和dnn是我手动添加的和工程文件 pro 同级目录的文件夹
里面分别包含了图片和模型文件:
 
再来看.pro中添加的这个部分
 
data.files += images/*.*
data.files += dnn/*.prototxt
data.files += dnn/*.caffemodel
data.path = /assets/dnn
INSTALLS += data
 
其中data字段是可以随便定义的,首先指定data.files 文件目录,然后将images目录下所有的文件,dnn目录下所有的.prototxt和.caffemodel
 
全部加入其中。最后制定data.path为/assets/dnn
 
这样编译出来的 apk 中,加压后会发现已经生成一个assets文件夹,并且在改文件夹中存放了我们已经添加的文件。
 
 
我们可以通过winrar打开apk,发现这些文件。
 
那么到目前为止,所有需要准备的东西都已经停当,我们开始编码。
 
二、代码编写
这里我给出的例子是一个非常简单的widget程序(截图可能和题图有所不同,以这里的为准)
 
包含1个textbox和2个button按钮。我们直接按照从上到下的顺序来看代码。
 
首先是"读取Lena并显示“,这个按钮的功能比较存粹,就是使用OpenCV从前面保存的assets目录中读出lena.jpg,并且最终利用QT显示出来。
 
void MainWindow::on_pushButton_2_clicked()
{
QFile::copy("assets:/dnn/lena.bmp", "lena.bmp");
Mat src = imread("lena.bmp");
cvtColor(src,src,COLOR_BGR2GRAY);
QPixmap qpixmap = Mat2QImage(src);
// 将图片显示到label上
ui->label->setPixmap(qpixmap);
}
 
逐句来看,首先使用QFile::copy函数将"assets:/dnn/lena.bmp"拷贝到根目录下的"lena.bmp"处,这样OpenCV就能够使用绝对路径来读取;
 
接下来读入这个图片,转换为灰度图片,这些都是基本OpenCV函数。然后我们使用了Mat2QImage函数将Mat格式的数据转换成为了QPixmap格式,并且使用label显示出来。
 
那么Mat2QImage是一个我们自己实现的函数,功能就是将Mat格式转换为QImage格式,这样QT就能够显示。
 
)
{
cvtColor( src, tmp, COLOR_BGR2RGB );
img = QImage( (const unsigned char*)(tmp.data), tmp.cols, tmp.rows, QImage::Format_RGB888 );
}
else
{
img = QImage( (const unsigned char*)(src.data), src.cols, src.rows, QImage::Format_Grayscale8 );
}
QPixmap qimg = QPixmap::fromImage(img) ;
return qimg;
}
其次是“调用着色算法”,这个函数就是在前面的基础上添加了较多功能。
 
;
;
Net net , , , };
, sz, CV_32F, hull_pts);
Ptr, , CV_32F, Scalar(.)));

. );
cvtColor(tmp, lab, COLOR_BGR2Lab);
extractChannel(lab, L, );
cv;

], result.size[]);
Mat a , ));
Mat b , ));
cv, lab);
cvtColor(lab, color, COLOR_Lab2BGR);

color.convertTo(tmp,CV_8UC3,);

QPixmap qpixmap = Mat2QImage(tmp);
// 将图片显示到label上
ui->label->setPixmap(qpixmap);
}

这个代码比较长,我们一块一块地来讲,首先仍然是将assets目录中的文件拷贝到绝对地址下面;
然后这个比较长的代码具体实现的功能就是调用模型实现着色效果,这里我整编一些之前写的东西。
 
目前使用的这个模型来自Richard Zhang,原始论文:
目前算法能够实现较好的灰度图片作色效果,他所采用的方法是基于大量图片的训练来“预测”灰色图片中对应的彩色效果。下图是论文中的对比。
 
为了程序的成功运行,需要先前往

http://eecs.berkeley.edu/~rich.zhang/projects/2016_colorization/files/demo_v2/colorization_release_v2.caffemodel

https://raw.githubusercontent.com/richzhang/colorization/master/colorization/models/colorization_deploy_v2.prototxt

下载caffeemodel和prototxt文件。整个过程中很多代码,只有几行是核心的:

其他的代码都是为了能够将各种文件转换成forward支持的格式。其中调用了一个大的常量:

., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .,
., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., ., .
};

这些数据的产生都和作者原始采用的模型有密切关系,想要完全理解Dnn的代码就必须了解对应模型的训练过程。

 
参考和技巧
1、看到我这里使用“夜神”模拟器来调试Android程序是不是很感兴趣?具体使用起来是有技巧滴,请参考

如何使用”夜神“作为虚拟机来进行程序调试

 
2、在QTCreator的“工具->外部”选项下,可以配置一些外部程序,比如我把“夜神”和"SDK Manger"配置在这里,方便使用
 
            
3、发现Qt Creatror使用designer修改了界面但是编译无反应的解决方法,请具体参考
 
4、配置过程的参考建议。
        这里分为3个步骤,首先是使用QT编写Android程序,然后是实现Android+OpenCV,最后是Android+OpenCV+DNN,应该说是渐进方式的,每个步骤都有不同的参考资料。
 
        step1:配置QT编写Android程序
 
 
         step3:Android+OpenCV+DNN
        
5、各个软件下载地址,注意优先选择X86_64版本
 
 
 
 
 
6、最后,提供完整的代码。但是你需要根据机器的实际情况进行修改
链接:https://pan.baidu.com/s/1oYo4iTihkKuG8eneBV7tmQ 
提取码:00k9 
 
         总体感觉,开发基于Android的图像处理程序,是一件比较繁琐的事情,可能出现问题的地方比较多,特别是QT的资料相对较少;但是一旦配置成功、摸清楚其中的原理之后,就能够非常方便地将桌面图像程序算法移植过来,但是也需要注意算法移植过程中的一些小技巧。
            感谢阅读至此,希望有所帮助!
 

搭建Android+QT+OpenCV环境,实现“单色图片着色”效果的更多相关文章

  1. 使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程)

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  2. 搭建Android底层开发环境

    为了开发linux驱动方便些,我们一般将linux作为Android的开发环境,那么就需要搭建Android的开发环境,下面是一些搭建Android底层时的心得: (1)安装JDK:除了普遍使用的下载 ...

  3. Android开发新手学习总结(一)——使用Android Studio搭建Android集成开发环境

    [新手连载]一:使用Android Studio搭建Android集成开发环境http://bbs.itcast.cn/forum.php?mod=viewthread&tid=87055&a ...

  4. 使用Android Studio搭建Android集成开发环境(图文教程)

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  5. 使用Android Studio搭建Android集成开发环境

    有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环 ...

  6. 如何在Ubuntu下搭建Android NDK开发环境

    1 搭建Android SDK开发环境 参考在在Ubuntu下搭建Android SDK开发环境(图文)首先在Ubuntu下搭建Android SDK开发环境. 2 下载NDK开发包 打开官网: ht ...

  7. Android开发学习总结(二)——使用Android Studio搭建Android集成开发环境

    有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环 ...

  8. Windows下搭建Android NDK开发环境及命令行编译

    首先说明本文内的相关安装操作参考<Pro Android C++ with the NDK>一书. 安装 Windows搭建Android NDK开发环境需要安装如下部分(同时需要配置对应 ...

  9. 搭建 Android 集成开发环境

    在搭建 Android 集成开发环境之前,我想说的是,我们学习的目标是同时掌握移动开发三种方式:iOS开发.Android开发和Html5手机网页开发.由于iOS的开发工具是采用苹果官方的XCode, ...

随机推荐

  1. GStreamer基础教程07 - 播放速率控制

    摘要 在常见的媒体播放器中,通常可以看到快进,快退,慢放等功能,这部分功能被称为“特技模式(Trick Mode)”,这些模式有个共同点:都通过修改播放的速率来达到相应的目的. 本文将介绍如何通过GS ...

  2. [Flowable] - 工作流是什么?BPM是什么?

    工作流管理系统基本概念 近两年随着电子商务环境不断演进(例如阿里巴巴的B2B电子商务平台),从原来支持企业内部单系统的业务流程.到企业内部应用.服务的集成,再进一步向企业与合作伙伴之间业务交互,工作流 ...

  3. HBase 系列(八)——HBase 协处理器

    一.简述 在使用 HBase 时,如果你的数据量达到了数十亿行或数百万列,此时能否在查询中返回大量数据将受制于网络的带宽,即便网络状况允许,但是客户端的计算处理也未必能够满足要求.在这种情况下,协处理 ...

  4. 渗透之路基础 -- 跨站脚本攻击XSS

    目录 漏洞原理及防御 XSS 原理分析:输出问题导致js代码被识别执行 XSS 技术分类 Cookie盗取 基于Xss的WebShell箱子的攻击 XSS相关防护过滤及绕过分析(参考链接) 防护: 绕 ...

  5. go 学习笔记之万万没想到宠物店竟然催生出面向接口编程?

    到底是要猫还是要狗 在上篇文章中,我们编撰了一则简短的小故事用于讲解了什么是面向对象的继承特性以及 Go 语言是如何实现这种继承语义的,这一节我们将继续探讨新的场景,希望能顺便讲解面向对象的接口概念. ...

  6. springboot之additional-spring-configuration-metadata.json自定义提示

    springboot之additional-spring-configuration-metadata.json自定义提示 简介 additional-spring-configuration-met ...

  7. MSIL实用指南-生成while语句

    本篇讲解怎样生成while语句.while语句是编程语言中很重要的循环语句,它的结构是while(<表达式>) <语句或语句块> 当表达式的结果为true时就一直执行语句或语句 ...

  8. Java NIO之理解I/O模型

    前言 自己以前在Java NIO这块儿,一直都是比较薄弱的,以前还因为这点知识而错失了一个机会.所以最近打算好好学习一下这部分内容,我想应该也会有朋友像我一样,一直想闹明白这块儿内容.但是一直无从下手 ...

  9. This probably means that Tcl wasn't installed properly.

    报错 D:/Anaconda3/tcl/tcl8.6/init.tcl: version conflict for package "Tcl": have 8.6.8, need ...

  10. hdu 1007 Quoit Design(分治)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给出n个点求最短的两点间距离除以2. 题解:简单的分治. 其实分治就和二分很像二分的写df ...