Day 07 预览图拍摄和数据归档
Day 07 拍摄预览图基本流程接下来实现拍摄预览图的函数doPreview()。
预览图拍摄阶段要做的活动包括:
调用GetSlidePreview()拍摄样本的预览图和标签图,并解析出标签上的条码/二维码内容
保存预览图和标签图到本地硬盘中和扫描档案文件中
解析标签图,识别出样本编号和样本类型
(可选)弹出对话框,让用户确认和修改样本编号和扫描参数等信息
保存扫描参数到索引文件
利用预览图找出要进行低倍扫描的范围
(可选)弹出对话框,让用户确认和修改低倍扫描的范围
从这里我们发现,要实现拍摄预览图,还有很多基础工作要做。我们先不考虑这些,尽量写一个初稿出来:
1234567891011121314151617181920212223242526bool ScanTask::doPreview(){ int retval; std::vector<PicInfor> picList; ScanInfo scanInfo; auto cleanup = qScopeGuard([&picList](){ ...
Day 6 实现扫描业务类
Day 6 实现扫描业务类ScanTask接下来要实现扫描业务。这将是软件比较复杂的一部分,我们将先抛弃界面部分,集中于业务管理。扫描活动是一个耗时操作,为了避免界面阻塞,我们需要在单独的线程中运行它。另外,它本身也会有很多需要并发执行的任务,也将会包含诸多的工作线程。本章开始我们的工作重点将是各种线程模式的使用。在多线程中运行ScanTask将放在界面部分讨论,我们重点关注ScanTask内部的多线程机制。
ScanTask概述当设备可用后,我们就可以进行扫描活动了。我们先看一下扫描的过程:
简单的来说,一张玻片样本的扫描步骤由下面几步组成:
12flowchart LR 进片 --> 拍摄预览图 --> 计算低倍扫描区域 --> 低倍扫描 --> 计算高倍扫描区域 --> 高倍扫描 --> 高倍扫描 --> 退片
进片:扫描仪移动载物台,将载物台移动到预览相机下面,拍摄样本全局图和标签图。这一步是由驱动的GetSlidePreview()实现的。
计算低倍扫描区域:软件对拍摄到的预览图做分析,根据玻片类型和扫描要求寻找出需要进行 ...
Day 5 扫描驱动桩开发
Day 5 扫描驱动桩开发关于扫描仪显微扫描设备是稀缺且昂贵的设备,并且扫描过程繁复(厂商提供的驱动,必须按照低倍-高倍的顺序进行,且百倍油镜一定会滴油,滴油之后如果再要做十倍扫描就需要再将油擦去),因此,前期的软件开发中,使用真实设备是很低效的工作。我们需要通过打桩的方式来实现开发前期对设备的替代。
首先定义接口IScanDevice。它是对提供的显微镜的接口的封装。我们在Adaptors项目中增加一个类IScanDevice,它为抽象接口类:
123456789101112class ADAPTORS_EXPORT IScanDevice{public: IScanDevice() = default; virtual int Initialize() = 0; virtual int GetSlidePreview(std::vector<PicInfor>* pic_list, ScanInfo* scan_info, std::string& qrcode) = 0; virtual int LowScanMoving(S ...
Day 04 配置器和多语种实现
Day 04 配置器和多语种实现前面提到了我们在开发Qt应用时,只要有支持多语种的可能,就应当开发原生英文界面,并利用翻译机制来支持中文。今天就讨论如何实现它。在实现翻译之前,首先要知道希望使用的语言。Qt提供的默认机制是根据当前系统的位置和系统设置来决定选择哪种语言,这种做法通常不符合人们的要求。一般来说,我们更希望能够自己控制并记录这种设置,而不是让电脑自己做决定。这就涉及到系统设置的读取和保存。
配置器Qt提供了配置支持的基础类QSettings,它支持使用注册表或ini文件的方式,支持读写操作,更重要的是它会自动检测配置源的变化,再读取QSettings对象,会得到更新后的值,而这对客户端是透明的。但是,直接使用QSettings类需要我们每次访问属性时都要提供冗长易错的配置项名称,这个太容易错了。所以我们需要封装出自己的设置类。
接下来要考虑如何提供这个接口,本质上,配置器在系统运行期间应该是唯一的,始终存在的,将其实现为Singleton是很自然的。但是实现为Singleton对单元测试不是很方便——我们还是希望在测试的时候能够有多种配置可以使用,并且最好不要互相影响。所以 ...
Day 3 构造基本界面元素
Day 03 构造基本界面元素首先我们构建主程序界面。通过基本界面的构建,我们可以进一步理清需求,明确模块接口。
界面草图严格讲,软件的界面应当做专门设计。如何构筑界面,尤其是如何美化界面,并不是我们在本书中关注的重点。在我们的示例项目中,为了减少无关的内容,我们对内容做了尽可能的简化,只保留和要讨论的内容有关的必要部分。我们也不考虑界面的美观等内容,以实现基本功能为目标,只要界面能显示需要显示的信息就可以了。
我的观点一直是,Qt这个东西,在以相同的成本前提下,要做出一个美轮美奂的界面上面,距离WPF差了十万八千里。在做出一个能用的基本界面的前提要求下,开发成本距离Web技术更是差了几个十万八千里。所以,它的根本点就不应该是在界面的外观上面。本书也不会把精力放在这上面。
下面就是我们打算用来实现的一个简单的界面:
菜单条,工具栏,状态栏等系统组件
整个应用窗口垂直方向分成左中右三部分:
左边自上而下由两个组件:上面是一个显示照片预览图的控件,下面是一个图像化显示扫描工作进度的组件
中间部分是扫描图像显示窗口,我们会用来在扫描过程中显示得到的图片
右边部分会用来实时显示扫描过程中 ...
Day 2 项目启动
Day 02 项目启动项目视图按照分层设计原则划定软件的模块,分成四个模块:
12graph TB CellScanner --> Frameworks --> Adaptors
其中,
CellScanner:应用程序的界面部分。
Frameworks:程序逻辑部分
Adaptors:和外部设备的接口
其中,CellScanner是一个应用程序,而另外两个是DLL。
Qt提供了两种界面开发路径:基于传统C++的Widgets和新的QML。在本书中,因为各种原因,我们将技术栈设定为纯C++/Widgets的开发,但是为了以后或许有机会切换到QML(这并不是一个好主意,甚至可能根本不可行,我认为),我们明确划分前后台的职责,将界面无关的逻辑放到framework项目中,将外部接口相关的内容放到adaptor里面去(扫描仪控制,AI功能接口以及网络接口)。
项目结构如下:
123graph TB ScanSuit --> Adaptors & Frameworks & CellScanner & UnitTest ...
Boost.DI
Boost.DI 学习笔记Boost.Ext.DI是一个用来实现依赖注入的框架. 依赖注入在Java和C#中使用的十分普遍, 但是在C++中则出现得比较少. 这个框架也一直没有被纳入到Boost的正式版本中.
对C++而言, 依赖注入是否是一个很重要的功能是值得商榷的, 因为就目前而言, C++实际上极少用于Java, C#这种Bussiness场景, 而是更多地用于底层功能实现. 其类层次的规模基本上是可控的, 而且, 实际上也不大存在大量的接口-实现类这种使用模式–确实比较少见.
下面的内容主要来自于其网站教程.
使用下载Boost.Ext.Di之后, 只要在代码里面包含di.hpp就可以了:
12#include "boost/di.hpp"namespace di = boost::di;
DI要求C++最低版本为C++14.
结论目前看用不到。先不浪费时间了。
Day 1 分析和规划
Day 1 需求分析和计划概述软件开发的第一步是业务和需求分析,明确软件的使用场景,业务目标,并在此基础上总结处软件的需求。这一过程有各种名称,各种方法,取决于不同的软件,领域,内外部环境等。一般而言,承接的外部需求,或者需要对外分包的系统,需求分析的要求就很高。对于复杂的系统,变更代价高昂的产品,前期需求分析的要求也比较高,而对于简单的,企业内部的项目,软件需求分析通常没有太高的,过于形式化的要求。而对于需求变化充满了不确定性的产品,则需要考虑原型技术。我们这个系统本身是一个大的系统的一部分,有明确的上级需求输入,规模也不大,因此并不需要太正规和形式化的需求分析。需求分析和软件架构设计通常是耦合在一起的。尤其是,当规划者,设计者,实现者是同一个/批人的时候,这些工作通常是在一起进行的。
简单的来说,我们需要做下面的几项工作:
明确外部功能和性能需求
明确业务场景和使用模式
明确硬件设备约束
明确子系统间的接口
首先是明确外部需求和使用场景/模式。外部需求一般是从产品规划处得到。通常,市场规划和产品分析会给出产品要实现哪些功能和特性,要达到多高的性能,可靠性,成 ...
Day 0 前言
Day 0 前言题外话关于Qt是什么,Qt难不难,学起来容易不容易,应不应该学,网上有各种各样的讨论,本书不打算出版,所以不会在这种无聊的事情上浪费字数。既不会吹,也懒得黑。就我个人的经历感受看,一个人在工作种选择哪种语言,选择哪种技术,通常是身不由己的。你身处这个位置,被要求使用某种技术,不管你会不会,你喜不喜欢,你都要想会,要么你就走人。而从另一个方面来说,一种语言,一个框架,说到底是一个给人使用的工具,不管是上古的Cobel,Fortran还是现在火的不得了的Go,Rust(比如,最近稀宗同志就公然宣称C++不安全,要求改用Rust😓),本质上和一个钳工手里的锤子,电工手里的试电笔没有区别。我从未见过一个电工因为手里拿的是某世的试电笔就觉得自己可以傲视那些拿着杂牌试电笔的电工了,但是这种情况在程序员里面却十分常见,令我多年来都感到即有趣又费解。毕竟,这仅仅是工具,又不是名牌跑车皮包首饰啥的。
追根溯源,网络上关于语言的争论很多是培训机构在捣鬼,而一个企业从一种技术栈切换到另一种技术栈,一般来说也绝对不是纯粹的技术的原因,更多的是政治上的考量。更多的不再讨论。作为一名工程师,当前 ...
Hello World
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
Quick StartCreate a new post1$ hexo new "My New Post"
More info: Writing
Run server1$ hexo server
More info: Server
Generate static files1$ hexo generate
More info: Generating
Deploy to remote sites1$ hexo deploy
More info: Deployment