当前位置: 首页 > news >正文

跨平台之用VisualStudio开发APK嵌入OpenCV(三)

本篇将包含以下内容:

1.使用 Visual Studio 2019 开发一个 Android 的 App

2.导入前篇 C++ 编译好的 so 动态库

3.一些入门必须的其它设置

作为入门,我们直接使用真机进行调试,一方面运行速度远高于模拟器,另一方面模拟器使用的 CPU 跟开发主机是一样的 x86,而前篇 C++ 编译的 .so 动态库是 ARM RISC CPU,所以……

作为公益技术博客,我暂时没有开启打赏,不过如果有很多小朋友疯狂点赞,威逼利诱可以追加一篇相关的杂七杂八的设置和基础知识解说

开始吧

新建一个项目,过滤“C#”,“所有平台”,“移动”,选择“移动应用(Xamarin Forms)”

如果从 Android Studio 转过来,或者打算转向 Android Studio 可以选择上图第二项

应用名写 Transformer(不是变形金刚)

为了简单起见,直接选择空白应用,理论上 Xamarin 可以让代码在安卓、苹果、Windows 上运行(至少他们是这么吹的),你可以全部勾选,对于本例我们实际只用 Android

点击创建,实际会生成 4 个项目,分别是 Android,iOS,Windows 的应用项目,还有一个公用的 DLL 核心,前面3个项目是特定平台的应用,但实际的界面和业务逻辑(功能)在 DLL 项目

现在开始折腾UI界面,双击打开 Transformer 项目的 MainPage.xaml 文件,直接在自动生成的控件后面加一个按钮,直接使用自动生成 Click 事件

关于 MVVM 设计模式以及 xaml 语法什么的,以后得空随缘更新吧

再添加一个 Image 用于显示透视裁切的效果,设定 Name 为 image1

展开 MainPage.xaml 树,双击打开 MainPage.xaml.cs 代码文件

声明一个接口,编写 Click 事件代码

虽然我一贯反对复制粘贴,不过时代这种东西……


private async void Button_Clicked(object sender, EventArgs e)
{var status = await Xamarin.Essentials.Permissions.CheckStatusAsync<Xamarin.Essentials.Permissions.StorageRead>();if (status != Xamarin.Essentials.PermissionStatus.Granted){status = await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.StorageRead>();}if (status == Xamarin.Essentials.PermissionStatus.Granted){status = await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.StorageWrite>();}if (status == Xamarin.Essentials.PermissionStatus.Granted){IStorage storage = DependencyService.Get<IStorage>();var file = storage.Demo();this.image1.Source = ImageSource.FromFile(file);}
}

双击打开 Transformer.Android 项目的 MainActivity.cs 文件

在 Android 项目下实现上面所说的接口,iOS 也另外实现,Windows 同理,但是都可以通过公用的 DLL 项目调用,这就是接口的本质

可以复制粘贴的代码

public class StorageService : Transformer.IStorage
{[System.Runtime.InteropServices.DllImport("libPerspectiveTransformer.so")]public static extern void TransformFile(string src, IntPtr src_xys, string dst, IntPtr dst_size);public string Demo(){var downloads = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);string root = downloads.AbsolutePath;var src = System.IO.Path.Combine(root, "card.jpg");var dst = System.IO.Path.Combine(root, "card_trans.jpg");TransformFile(src, IntPtr.Zero, dst, IntPtr.Zero);return dst;}
}

一行也算哎

Xamarin.Forms.DependencyService.Register<Transformer.IStorage, StorageService>();

至于这些代码都是什么意思,以后得空随缘更新吧

你可以网上搜,当然如果你求助 AI 国内的大模型跟 ChatGPT 是没法比的,经常给出错误的回答,不过也可以给出一些启发什么的(为什么这些人那么有钱,不让我拿去搞呢)

接下来是关键,引入前面 C++ 编译的 so 动态库

添加一个文件夹

再添加一个 armeabi-v7a 下一级文件夹

关于这个具体是什么意思,你可以网上搜,但是不要问女朋友

你可以简单理解为针对不同的 CPU 类型,暂时不支持 x86、x64(AMD64,x86_64)、ARM64 以及古老的 armeabi 即 64 位最新的手机兼容运行,老旧的手机不能运行,然后双系统平板和电脑端模拟器不能运行(2011年以后大部分的安卓手机和平板都可以运行)

然后,导入 so 动态库文件

选择上一篇 C++ 编译好的 so 文件

属性设置:复制到输出目录=始终复制;生成操作=AndroidNativeLibrary

这一步非常关键,即便你跑去国外查,也很难查得到

很多人是打包成Nuget的方式再引入的,坦白说欧美的教育是重启发、轻知识,1+1=2导师都要你自己去思考,而不直接给你答案

然后我们就可以编译、在手机上调试了

首先,把 Transformer.Android 设为启动项目

项目右键属性,修改以下名称(也可以保持默认

然后是权限,勾选外部存储读写权限

权限是必须的,在 Android 5.0 (Lollipop,棒棒糖) 以后是动态获取权限(为什么是棒棒糖?)

关于权限,安卓包的结构,异步,各种杂七杂八的,以后得空随缘更新吧

反正示例的代码已经包含有最精简的基本操作

使用 USB 连接手机,本次调试用的是较旧的二手小米 Redmi 6A 手机,小米手机开启开发者模式需要登陆,注册是免费的,关于手机怎么开启开发者模式,你可以网上搜,大把多

将 USB 连接方式设置为“传输文件”,把示例的图片card.jpg复制到手机的这个文件夹

如果不想翻前一篇,图片是这样的(来源于网络),你可以用自己的图片,不过要自己修改坐标点

工具栏直接点 启动

在手机上点我们设计的“透视裁切”按钮,会弹出请求权限,同意后就显示转正效果

大功告成!

相关文章:

跨平台之用VisualStudio开发APK嵌入OpenCV(三)

本篇将包含以下内容&#xff1a; 1.使用 Visual Studio 2019 开发一个 Android 的 App 2.导入前篇 C 编译好的 so 动态库 3.一些入门必须的其它设置 作为入门&#xff0c;我们直接使用真机进行调试&#xff0c;一方面运行速度远高于模拟器&#xff0c;另一方面模拟器使用的…...

渗透测试框架之CobaltStrike,Metasploit域名上线隐藏IP

概述 为什么要隐藏IP 在拿下了目标机之后&#xff0c;目标机在内网里面&#xff0c;使用msf或者CS时&#xff0c;用自己的VPS做服务器的话&#xff0c;导致很容易被溯源。 域名上线原理 当我们访问域名时会经过域名解析 域名解析就是域名到IP地址的转换过程&#xff0c;那么…...

vue.js对接海康威视摄像头web开发包

一、登录海康开放平台下载web开发包&#xff0c;下载需要先登录海康账号&#xff0c;没有的需先注册一个。 这里的appkey、ip、port、secret 和cameraIndexCodeasd是自己去申请的 appkey: "****", ip: "****", port: **, secret: "****", //必填…...

Selenium中使用的三种等待

文章目录 1.前言2.在selenium中常见的等待操作一般有3个 1.前言 在使用selenium时很多元素在使用的时候都需要加载&#xff0c;如果不等待加载结束直接使用就会报错&#xff0c;功能不能继续。一般解决的办法就是使用等待操作。 2.在selenium中常见的等待操作一般有3个 slee…...

推荐一款媒体影音嗅探神器—Chrome扩展插件(猫抓cat-catch)

目录 1.1、前言1.2、下载地址1.3、github Releases 版本说明1.4、安装步骤1.5、猫抓插件常规设置1.5.1、设置抓取文件的类型1.5.2、设置抓取文件的后缀名 1.1、前言 我们在日常上网的过程中&#xff0c;很多音频、视频网站下载资源都非常不方便&#xff0c;要么需要安装客户端&…...

LLaMA-Factory 微调训练

LLaMA-Factory 微调训练 该框架功能&#xff0c;标注-微调-导出-合并-部署&#xff0c;一整条流程都有&#xff0c;而且训练时消耗的gpu算力也会小一些 一&#xff0c;安装&#xff08;推荐在linux中训练&#xff0c;win可以用wsldocker&#xff09; git clone https://githu…...

阿里云ECS服务器怎么设置时区

在自己部署在阿里云服务器上的应用中&#xff0c;控制台打印的日志时间和本地不一致&#xff0c;于是决定修改阿里云服务器的时区为Asia/Shanghai。 具体操作如下&#xff1a; 第一步&#xff1a;连接服务器 通过finalshell等连接工具通过公网IP连接到服务器。 第二步&#…...

【698协议】帧校验算法

698协议&#xff0c;帧校验算法 帧格式 帧校验范围 校验算法 #include "fcs16.h" /* * u16 represents an unsigned 16-bit number. Adjust the typedef for * your hardware. * Drew D. Perkins at Carnegie Mellon University. * Code liberally borrowed from M…...

FileZilla“服务器发回了不可路由的地址,使用服务器地址代替

问题&#xff1a;在宝塔创建的FTP无法使用&#xff0c;提示“服务器回应不可路由的地址。使用服务器地址代替 第一种解决办法&#xff1a;由于宝塔把FTP被动模式端口范围设置成了39000-40000&#xff0c;所以只需要把阿里云服务器上相应的端口范围开放即可。 第二种解决办法&am…...

【路径规划】基于遗传算法GA实现最短距离 多起点多终点多旅行商问题求解附Matlab代码

基于遗传算法GA实现最短距离 多起点多终点多旅行商问题求解 研究背景:研究步骤:研究方法和技术路线:代码研究背景: 多起点多终点多旅行商问题是旅行商问题(TSP)的一个扩展,该问题要求确定多个旅行商从各自的起点出发,分别经过一系列目标点最终回到各自的终点,使得总路…...

计算机毕业设计 | springboot+vue房屋租赁管理系统(附源码)

1&#xff0c;绪论 1.1 课题来源 随着社会的不断发展以及大家生活水平的提高&#xff0c;越来越多的年轻人选择在大城市发展。在大城市发展就意味着要在外面有一处安身的地方。在租房的过程中&#xff0c;大家也面临着各种各样的问题&#xff0c;比如需要费时费力去现场看房&…...

重大活动网络安全保障建设及运营指南

在当今高度数字化的社会中&#xff0c;各类重大活动如会议、展览、赛事及庆典等正面临着日益复杂和严峻的网络安全威胁。这些威胁不限于网络入侵或数据泄露&#xff0c;更涉及到对基础设施、关键信息系统和公众舆论的复杂攻击&#xff0c;需要国际社会的密切合作和长期关注。因…...

基于信号分解方法的机械故障诊断方法存在的问题

一方面&#xff0c;由于结构共振、测试噪声的干扰&#xff0c;为了确保分解精度&#xff0c;需要给定准确的参数初值(例如&#xff0c;瞬时频率)。研究人员通常认为零部件特征频率与通过传动比和驱动转速计算的理论值基本吻合&#xff0c;并基于理论值设置参数初值。事实上&…...

faster_whisper语音识别

faster_whisper语音识别 检测可用设备&#xff1a;list_available_devices()函数 我这边usb摄像头带麦克风的&#xff0c;所以 DEV_index 8 1 使用 pyaudio 打开音频设备 2 从音频设备读取数据&#xff0c;传递给 faster_whisper 识别 按键 r 录制 s 停止 q退出 test.py #…...

Java锁的策略

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f649; 内容推荐:<多线程案例(线程池)>&#x1f649; &#x1f439;今日诗词:"你我推心置腹, 岂能相负"&#x1f439; 目录 锁的策略 乐观锁和悲观锁 轻量级锁…...

521源码-免费代码基础学习-PHP如何运用变量教程

更多网站源码学习教程&#xff0c;请点击&#x1f449;-521源码-&#x1f448;获取最新资源 为什么要学习PHP&#xff1f;“我可以用JavaScript来实现程序编写。”但JavaScript的能力是有限的&#xff0c;JavaScript通常运行在浏览器&#xff08;客户端&#xff09;&#xff0…...

单选或者多选的知识问题调研系统,怎么使用Neo4j的图数据库来实现

为了使用Neo4j的图数据库实现单选或多选的知识问题调研系统&#xff0c;你需要设计和实现以下几个步骤&#xff1a; 设计节点和关系插入数据定义查询和更新逻辑开发前端和后端应用来与Neo4j进行交互 1. 设计节点和关系 节点类型 Question&#xff1a;表示一个问题&#xff…...

【微机原理及接口技术】可编程并行接口芯片8255A

【微机原理及接口技术】可编程并行接口芯片8255A 文章目录 【微机原理及接口技术】可编程并行接口芯片8255A前言一、8255A的内部结构和引脚1.与外设接口&#xff08;数据端口&#xff09;2.与处理器接口 二、8255A的工作方式三、8255A的编程1. 写入方式控制字&#xff1a;控制字…...

第3天 Web源码拓展_小迪网络安全笔记

1.关于web源码目录结构 #数据库配置文件 后台目录 模板目录 数据库目录 1.1数据库配置文件: 1.1就拿wordpress来说,先到官网下载源码:Download – WordPress.org,解压源码之后: 2.2找到目录下名为 wp-config-sample.php的文件,这就是数据库配置文件: 设想: 我们在渗透…...

基于物联网技术的智能家居实训教学解决方案

引言 随着信息技术的飞速发展&#xff0c;&#xff0c;物联网&#xff08;IoT&#xff09;已深入至我们生活的每一个角落&#xff0c;从智能家居、智能健康、智能交通到智慧城市&#xff0c;无所不在。物联网技术已成为推动社会进步和产业升级的重要力量。智能家居作为物联网技…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...