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就能够显示。
//格式转换
QPixmap Mat2QImage(Mat src)
{
QImage img;
//根据QT的显示方法进行转换
if(src.channels() == 3)
{
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;
}
其次是“调用着色算法”,这个函数就是在前面的基础上添加了较多功能。
void MainWindow::on_pushButton_clicked()
{
QFile::copy("assets:/dnn/lena.jpg", "lena.jpg");
QFile::copy("assets:/dnn/colorization_deploy_v2.prototxt", "colorization_deploy_v2.prototxt");
QFile::copy("assets:/dnn/colorization_release_v2.caffemodel", "colorization_release_v2.caffemodel");
Mat src = imread("lena.jpg");
cvtColor(src,tmp,COLOR_BGR2GRAY);
cvtColor(tmp,src,COLOR_GRAY2BGR);

string modelTxt = "colorization_deploy_v2.prototxt";
string modelBin = "colorization_release_v2.caffemodel";
bool useOpenCL = true;

// fixed input size for the pretrained network
const int W_in = 224;
const int H_in = 224;
Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
if (useOpenCL)
net.setPreferableTarget(DNN_TARGET_OPENCL);

// setup additional layers:
int sz[] = { 2, 313, 1, 1 };
const Mat pts_in_hull(4, sz, CV_32F, hull_pts);
Ptr<dnn::Layer> class8_ab = net.getLayer("class8_ab");
class8_ab->blobs.push_back(pts_in_hull);
Ptr<dnn::Layer> conv8_313_rh = net.getLayer("conv8_313_rh");
conv8_313_rh->blobs.push_back(Mat(1, 313, CV_32F, Scalar(2.606)));

// extract L channel and subtract mean
Mat lab, L, input;
src.convertTo(tmp, CV_32F, 1.0 / 255);
cvtColor(tmp, lab, COLOR_BGR2Lab);
extractChannel(lab, L, 0);
cv::resize(L, input, Size(W_in, H_in));
input -= 50;

// run the L channel through the network
Mat inputBlob = blobFromImage(input);
net.setInput(inputBlob);
Mat result = net.forward();

// retrieve the calculated a,b channels from the network output
Size siz(result.size[2], result.size[3]);
Mat a = Mat(siz, CV_32F, result.ptr(0, 0));
Mat b = Mat(siz, CV_32F, result.ptr(0, 1));
cv::resize(a, a, src.size());
cv::resize(b, b, src.size());

// merge, and convert back to BGR
Mat color, chn[] = { L, a, b };
merge(chn, 3, lab);
cvtColor(lab, color, COLOR_Lab2BGR);

color.convertTo(tmp,CV_8UC3,255);

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支持的格式。其中调用了一个大的常量:

static floathull_pts[] ={
-90., -90., -90., -90., -90., -80., -80., -80., -80., -80., -80., -80., -80., -70., -70., -70., -70., -70., -70., -70., -70.,
-70., -70., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -50., -50., -50., -50., -50., -50., -50., -50.,
-50., -50., -50., -50., -50., -50., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -30.,
-30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -20., -20., -20., -20., -20., -20., -20.,
-20., -20., -20., -20., -20., -20., -20., -20., -20., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10.,
-10., -10., -10., -10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 10., 10., 10., 10., 10., 10., 10.,
10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20.,
20., 20., 20., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 40., 40., 40., 40.,
40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 50., 50., 50., 50., 50., 50., 50., 50., 50., 50.,
50., 50., 50., 50., 50., 50., 50., 50., 50., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60.,
60., 60., 60., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 80., 80., 80.,
80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 90., 90., 90., 90., 90., 90., 90., 90., 90., 90.,
90., 90., 90., 90., 90., 90., 90., 90., 90., 100., 100., 100., 100., 100., 100., 100., 100., 100., 100., 50., 60., 70., 80., 90.,
20., 30., 40., 50., 60., 70., 80., 90., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -20., -10., 0., 10., 20., 30., 40., 50.,
60., 70., 80., 90., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -40., -30., -20., -10., 0., 10., 20.,
30., 40., 50., 60., 70., 80., 90., 100., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -50.,
-40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -60., -50., -40., -30., -20., -10., 0., 10., 20.,
30., 40., 50., 60., 70., 80., 90., 100., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90.,
100., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -80., -70., -60., -50.,
-40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -90., -80., -70., -60., -50., -40., -30., -20., -10.,
0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30.,
40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70.,
80., -110., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100.,
-90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100., -90., -80., -70.,
-60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -110., -100., -90., -80., -70., -60., -50., -40., -30.,
-20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0.
};

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

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

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

2、在QTCreator的“工具->外部”选项下,可以配置一些外部程序,比如我把“夜神”和"SDK Manger"配置在这里,方便使用
3、发现Qt Creatror使用designer修改了界面但是编译无反应的解决方法,请具体参考

Qt Creatror使用designer修改了界面但是编译无反应的解决方法

 
4、配置过程的参考建议。
这里分为3个步骤,首先是使用QT编写Android程序,然后是实现Android+OpenCV,最后是Android+OpenCV+DNN,应该说是渐进方式的,每个步骤都有不同的参考资料。
step1:配置QT编写Android程序
https://blog.csdn.net/yongheng0852/article/details/78875855
https://www.cnblogs.com/MakeView660/p/11206268.html
https://www.cnblogs.com/jsxyhelu/p/8286476.html
step2:Android上运行OpenCV
https://blog.csdn.net/u012230798/article/details/86620400
https://www.cnblogs.com/jsxyhelu/p/8449222.html
https://blog.csdn.net/tututuo/article/details/83419612

step3:Android+OpenCV+DNN
https://blog.csdn.net/m0_38133212/article/details/88032546
https://blog.csdn.net/m0_38133212/article/details/87979923
https://blog.csdn.net/luoyayun361/article/details/84800539
5、各个软件下载地址,注意优先选择X86_64版本
 
Android SDK https://www.androiddevtools.cn/
Android NDK https://developer.android.google.cn/ndk/downloads/index.html
Qt+QTCreator https://www1.qt.io/download-open-source-access/
OpenCV4Android https://sourceforge.net/projects/opencvlibrary/files/4.1.0/opencv-4.1.0-android-sdk.zip/download
6、最后,提供完整的代码。但是你需要根据机器的实际情况进行修改
链接:https://pan.baidu.com/s/1oYo4iTihkKuG8eneBV7tmQ 
提取码:00k9 

总体感觉,开发基于Android的图像处理程序,是一件比较繁琐的事情,可能出现问题的地方比较多,特别是QT的资料相对较少;但是一旦配置成功、摸清楚其中的原理之后,就能够非常方便地将桌面图像程序算法移植过来,但是也需要注意算法移植过程中的一些小技巧。
感谢阅读至此,希望有所帮助!

搭建Android+QT+OpenCV环境,实现“单色图片着色”效果相关推荐

  1. 使用飞凌嵌入式IMX6UL-C1板子——qt+opencv环境搭建

    使用飞凌嵌入式IMX6UL-C1板子--qt+opencv环境搭建 准备工作: Ubuntu18.04虚拟机环境 飞凌官方提供的qt-tslib库,gcc交叉编译器,opencv源码库,qt源码,具体 ...

  2. OpenCV图像处理--Qt+OpenCV环境搭建

    LinuxQt+Opencv 环境搭建参照 LinuxQT+第三方库配置 WindowsQt+OpenCV环境搭建 一.下载opencv环境 opencv环境下载 2.Qt+OpenCV环境测试 新建 ...

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

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

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

    一.Android Studio简单介绍 2013年GoogleI/O大会首次发布了Android Studio IDE(Android平台集成开发环境).它基于Intellij IDEA开发环境,旨 ...

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

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

  6. 安卓安装之离线搭建Android Studio开发环境

    离线搭建Android Studio开发环境 前言: Android Studio开发环境,有两种方式进行安装. ①:在线安装,需要下载大量的文件,最好电脑进行翻墙,否则下载速度相当的慢. ②:离线安 ...

  7. Win7环境下搭建Android安卓开发环境

    Win7环境下搭建Android安卓开发环境(原创教程) 此教程以32位win7旗舰版系统为基础,其它版本系统请根据情况自行调整.教程在2012年9月16日写,所有软件为当时的最新版. 准备文件(文件 ...

  8. 鸟人的Android揭秘(5)——搭建Android SDK开发环境(一)

    前面已经完整讲解了Android平台的构成,以及从Git服务器下载源代码并进行编译的内容.接下来讲解如何搭建Android SDK开发环境,包括Android Studio.Sublime.Andro ...

  9. 《Android多媒体应用开发实战详解:图像、音频、视频、2D和3D》——1.3节搭建Android应用开发环境...

    本节书摘来自异步社区<Android多媒体应用开发实战详解:图像.音频.视频.2D和3D>一书中的第1章,第1.3节搭建Android应用开发环境,作者 王石磊 , 吴峥,更多章节内容可以 ...

最新文章

  1. 字节一面:Redis主节点的Key已过期,但从节点依然读到过期数据....
  2. 【干货51页PPT】深度学习理论理解探索
  3. Zoom Capability
  4. linux bash command not found
  5. 2020\Simulation_2\4.括号序列
  6. python:copy()和deepcopy()区别
  7. 一个高质量的程序应具备哪些条件?_如何开好一个精品店?需要具备哪些条件?...
  8. C# 读写ACCESS的OLE对象,演示图片与长文件的读写
  9. python变量类型是动态的_python内存动态分配过程详解
  10. sql2008中打开“外围应用配置器”和启用 OpenRowSet 和 OpenDataSource函数
  11. 服务器上的文件如何查看,如何查看远程服务器上的文件
  12. 初识AngularJS 之 HelloWorld和数据绑定
  13. 孙鑫VC学习笔记:第十一讲 (六) 图形重绘方法二 利用元文件
  14. 完美二叉树, 完全二叉树和完满二叉树
  15. keil交通灯c语言,用Keilc软件设计一个交通灯程序C程序
  16. sql prompt linux,SQL PROMPT的设置
  17. CREO图文教程:三维设计案例之风扇叶制作图文教程之详细攻略
  18. android炫酷的效果
  19. 利用python实现华氏温度和摄氏温度的转换
  20. 人称代词的各种形式与用法

热门文章

  1. 心情不好的时候,就去做这5件事
  2. 2018年4月前端必须star的github项目
  3. OSChina 周一乱弹 ——看见别人的工作台眼神都发光
  4. 将url网址转换成对象
  5. alt 和 title 的区别
  6. 线段树专题 A(单点更新)
  7. MySQL双机热备份实施方案
  8. 梦想中的办公之所!华为云(莲湖)联合发展中心用四招让幸福工作成为可能
  9. 1068 万绿丛中一点红 (20分)
  10. OA系统,架起企业异地办公的桥梁