开始干
新建解决方案,新建动态库(Android)项目
功能随便选一个吧,就模仿PS(Photoshop)的透视裁切功能,一个物体(比如扑克牌)透视图,选4个顶点,转换为平面正视图,毕竟Xamarin很难实现这一类的功能(当然它最大的意义是让Android能够运行C#编写的代码)
下图来源网络
Visual Studio 2019的安装应该都会了吧
运行
然后过滤选择“所有语言”、“所有平台”、“其它”,选择空白解决方案(你可以直接新建项目,我不喜欢一串文件夹都是一个名称,辨识度太低)
我就默认Solution1了,位置我直接放桌面
然后桌面应该创建了这样子的文件夹
新建一个项目
过滤“C++”、“所有平台”、“移动”,选择“共享动态库(Android)”
名称就设为“PerspectiveTransformer”
还记得上文说到,你想要的吗,OpenCV已经编译好的静态库在这里
注意libs文件夹是给Java用的,也就是折腾Android Studio的那帮人,严格说那才是Android正统的开发环境(如果你刚开始学,现在折腾Java也不迟,它跟C#很像,或者应该说C#是跟大多数语言都很像),而静态库又分成几个这个
关于ABI(安卓二进制接口,你可以理解为CPU不一样)还有ARM RISC、x86 CISC指令集以后有空随缘更新再说吧(自认为老手的程序员骂骂咧咧关闭了浏览器选项卡)
如果你折腾的是源码,你会发现OpenCV没有include所需的.h/.hpp文件
因为需要编译(makefile)以后才把那些文件集中起来(你又想骗我自己编译OpenCV)
上文说到OpenCV那帮人已经帮你编译好了,在这里
现在打开cpp文件自己定义这样一个函数
实现代码为:
void TransformFile(const char* src, float* src_xys, const char* dst, float* dst_size)
{
static float default_xy[] = { 8, 190, 151, 56, 139, 249, 276, 103 };
if (src_xys == nullptr) { src_xys = default_xy; }
cv::Point2f src_marks[4] = {
cv::Point2f(src_xys[0], src_xys[1]),
cv::Point2f(src_xys[2], src_xys[3]),
cv::Point2f(src_xys[4], src_xys[5]),
cv::Point2f(src_xys[6], src_xys[7])
};
static float default_size[] = { 513, 328 };
if (dst_size == nullptr) { dst_size = default_size; }
cv::Size z(dst_size[0], dst_size[1]);
cv::Point2f dst_marks[4] = {
cv::Point2f(0, 0),
cv::Point2f(z.width, 0),
cv::Point2f(0, z.height),
cv::Point2f(z.width, z.height)
};
auto m = cv::getPerspectiveTransform(src_marks, dst_marks);
cv::Mat src1 = cv::imread(src);
cv::Mat dst1;
cv::warpPerspective(src1, dst1, m, z);
cv::imwrite(dst, dst1);
}
作为入门文章,精简即是要诀,直接通过文件传递数据即可(搭配示例图片可以不需要坐标参数)
函数功能是读取一个文件,根据提供的关键点截取、摆正、保存
你可以使用这样的硬编码包含opencv.hpp文件
也可以给项目添加include路径(就好像C++初恋一样)
点添加图标
选择上面提到的文件夹即可
打开或者编译,你就直到opencv.hpp包含了其它的hpp文件,但是没有使用相对路径,所以简易还是设置include目录,否则你就要修改很多hpp文件
设置好应该是
对于ARM64以及x86(常见是模拟器,以及双系统平板)等同样设置,此外还有Debug和Release模式(一个是调试版,一个是发行版)
因为OpenCV带有很多C++模板,里面有try-catch异常捕捉,所以要打开相关的参数
接下来是库设置,也是导入OpenCV编译好的静态库的关键
共有2个位置(不同平台不同,比如x86用的是x86文件夹)
然后是依赖项,也就是静态库列表
所需的静态库列表为:
opencv_imgcodecs
opencv_imgproc
opencv_core
libwebp
ittnotify
tbb
tegra_hal
cpufeatures
libjpeg-turbo
libopenjp2
IlmImf
libtiff
libpng
z
m
stdc++
我建议还是尝试一次自己折腾的痛苦,那样你的进步会很快(怎么说呢,玄学)
cv::initInterTab2D(int, bool): error: undefined reference to 'sincos' 加一行 m 使用数学库(导入静态库不包含 前缀 lib 和 扩展名 .a否则只能硬编码全路径)
error: undefined reference to '__cxa_guard_acquire' 加一行stdc++
libopencv_imgcodecs.a ... error: undefined reference to 'cv::resize opencv_imgcodecs 放在 opencv_imgproc 前面(被依赖的库放后面)
error: undefined reference to 'cv::utils::trace::details::Region 添加 opencv_core
libopencv_imgcodecs.a ... error: undefined reference to 'opj_image_destroy' 添加 3rdparty\libs\armeabi-v7a 目录,引用 liblibopenjp2.a
libopencv_imgcodecs.a ... error: undefined reference to 'Imf_opencv::Chromaticities::Chromaticities 引用 libIlmImf.a
libopencv_imgcodecs.a ... undefined reference to 'png_destroy_read_struct' 引用 liblibpng.a
error: undefined reference to 'TIFFSetErrorHandler' 引用 liblibtiff.a
error: undefined reference to 'WebPGetFeaturesInternal' 引用 liblibwebp.a
undefined reference to 'carotene_o4t::isSupportedConfiguration()' 引用 libtegra_hal.a 这个可能搞深度学习算法的才熟悉
undefined reference to 'tbb::interface7::internal::task_arena_base::internal_terminate()' 引用 libtbb.a
undefined reference to 'gzopen' 引用内置的 libz.a 即加一行 z
libopencv_core.a ... undefined reference to 'android_getCpuFeatures' 引用 libcpufeatures.a
undefined reference to '__itt_thread_set_name_ptr__3_0' libittnotify.a
已启动生成…
1>------ 已启动生成: 项目: PerspectiveTransformer, 配置: Debug ARM ------
1>ANDROID_HOME=D:\\Microsoft\AndroidSDK\25
1>ANT_HOME=D:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Apps\apache-ant-1.9.3
1>JAVA_HOME=C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25
1>NDK_ROOT=D:\\Microsoft\AndroidNDK64\android-ndk-r16b
1>PerspectiveTransformer.vcxproj -> C:\Users\Administrator\Desktop\Solution1\ARM\Debug\libPerspectiveTransformer.so
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
编译成功,就得到了libPerspectiveTransformer.so动态库
下一篇,外面在安卓的App开发项目中使用它