关于C++设计模式
今天正式封城。还好上周趁着能出小区出去疯狂采购了一批菜肉,还能凑合几天。以后不知道会怎么样。
给关在家里没事做,决定把Design Patterns in Modern C++这本书认真读一下,把重要的东西翻译一下做个笔记,免得以前读书一样,读的挺好,过几天就忘记了。
染色体提取操作
染色体提取操作从图片中提取染色体: extractChromosomes()使用场景:用于手工提取染色体的场景. 对于人工做过阈值化处理的图片, 利用这个函数提取出染色体.
输入:
原始图像: 原始的分裂相图片. 作为提取的数据源, 提取出染色体的原始图片
标定图像: 经过图像擦除, 增强处理的分裂相图片, 使得染色体的轮廓更为突出, 和背景的差别更为明显. 用于识别染色体的轮廓.
原始图像和标定图像都是单通道的灰度图像. 当前, 扫描硬件仅支持8bit图像.
我们利用标定图像来识别染色体, 然后根据轮廓从原始图像中提取染色体的图像数据, 然后再做图像增强处理. 这样, 可以避免过于二值化的标定图像导致染色体的图像细节收到损失.
处理流程:
将图像取反.因为我们接下来要对图像做二值化, 图像的背景是更亮的颜色, 需要取反才行.
对图像做二值化处理几种二值化算法, 包括大津二值化, 普通的二值化. 对于手工提取染色体的这种场景, 因为前面做了阈值调整处理, 已经将背景颜色都拉到255了. 因此使用最普通的二值化就可以.
二值化之后, 可以做一次腐蚀膨胀处理, 滤掉其中 ...
QGraphicsPixmapItem不响应鼠标的问题
QGraphicsPixmapItem不响应鼠标的问题在重构一个派生于QGraphicsPixmapItem的类, 重写了其重绘函数, 实际上就是废弃了利用QGraphicsPixmapItem自己的paint()行为, 改为自行实现了. 但是写完了之后发现功能都正常, 但是就是无法响应鼠标点击操作, 而在别处通过程序触发的select事件它依然能够正常响应和更新显示.
这个问题很令人迷惑, 仔细复查代码才注意到, 在重构的过程中, 我删除了setPixmap()的调用. 所以问题就清楚了. QGraphicsPixmapItem重载实现了boundingRect()和shape()两个函数, 这两个函数的实现都是基于设置的QPixmap来进行的. 在重构时, 因为不使用它的重绘机制, 实际上是把它当作是QGraphicsItem来用, 只是因为修改基类影响到其他地方才没有动作.
问题修改就很容易了, 重载shape()就解决了:
12345678QPainterPath ChromosomePixmapItem::shape() const{ const int ...
ValueConverters.Net的使用
ValueConverters.Net的使用
在B站上看到的内容。记录下来
获取在NuGet中搜索ValueConverters. 找到的第一个就是:
https://github.com/thomasgalliker/ValueConverters.NET
使用步骤:1. 引用2. 在Resource中声明它. 例如:123<Window.Resources> <conv:BoolToVisibilityConverter x:Key="BoolToVisibilityInv" IsInverted="True" FalseValue="Collapsed"/></Window.Resources>
3. 使用:1234<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> & ...
Prism下的线程数据更新
MVVM下线程数据的更新问题背景按照Prism中的说法, Prism的Command本身是异步的. 但是我在使用中, 发现Command的实现总是会阻塞UI线程的, 也就是说默认情况下它总是在UI线程中运行的.
ViewModel中更新数据比如, 下面有两个耗时函数:
1234567891011121314151617public StatusCode RunTest1(){ Trace.WriteLine("RunTest1 Begin"); updateMsg?.Invoke("RunTest1"); Task.Delay(3000).Wait(); Trace.WriteLine("RunTest1 Finished"); return StatusCode.DCM_TENSCANMOVING_START;}public StatusCode RunTest2(){ Trace.WriteLine("RunTest2 Begin") ...
OpenCV中实现路径识别
路径识别在图像图元处理中, 经常需要涉及到路径的识别, 比如曲线的覆盖, 交叉等.总的来说, 大的方向上, 有几种手段:
一种方式是利用OpenCV的相关的形态学方法. 因为一般处理图像的时候总要使用OpenCV, 顺便将它用在这里也没啥不方便
另一种方法是利用Qt本身的一些路径的方法.
总的来说, 两种方法各有好处. 彼此都有一些对方不支持的手段, 最好的方法就是综合使用.
扩大或缩小多边形方法1:对于一个不规则的多边形, 不管是内缩还是外扩, 都没有现成的方法.一种最简单的做法是利用OpenCV提供的腐蚀膨胀功能.先在黑底上绘制并填充当前多边形, 然后做腐蚀/膨胀, 然后再findCounter, 得到的就是内缩/外扩后的多边形.
当多边形大小不大的时候, 性能也不需要考虑太多的时候, 这种做法不失为一种简单快速上手的方式.
方法2:利用仿射变换, 需要计算出收缩比例. 当需要缩小比例的时候这种方法很好用.
QSignalMapper
QSignalMapper类偶然在Qt的帮助文档中看到一个类,QSignalMapper,很有意思,似乎没有人关注过它。记录一下,说不定以后用得到。这个东西最大的好处应该是可以用于动态生成界面,而又避免使用字符串形式的connect操作吧?
粗略看了一下,似乎是在QButtonGroup,QActionGroup之前的东西,应该是用不到了。
使用QDataWidgetMapper映射模型到控件
设置自定义光标
核型分析软件需要做一个染色体编辑界面,修改鼠标的形状。
设置光标图像在Qt的GraphicsView中设置自定义的光标很简单.
使用图片的方式
使用要作为光标使用的图片创建一个QPixmap的对象
利用这个QPixmap创建一个QCursor
使用QGraphicsView::setCursor()来设置光标
最重要的一点是, 在创建Cursor的时候, 可以指定鼠标尖的位置, 不然鼠标光标行为会很怪异.
123456view->setDragMode(QGraphicsView::DragMode::NoDrag);QPixmap stick_map = QPixmap(":/resources/images/Icon-cursor/curson-brush.png") .scaled(20,20, Qt::KeepAspectRatio, Qt::SmoothTransformation);// 钢笔相撞, 热点为坐下教的笔尖位置. 向内收缩两个像素值.QCursor cursor(stick_map ...
定义一个颜色选择的ComboBox
代码中要实现一个颜色选择的下拉框,从Qt的例子中找到一个。记录下来。这段代码的核心是,正如在Model/View中提到的,QCombox等内部都使用了Model。这是一个例子。看到这个例子,可以对Model/View有了更深刻的理解。
定义一个颜色选择的ComboBox来自Qt的例子程序 coloreditorfactory的一部分, 演示如何创建一个选择颜色的下拉框. 它产生一个使用颜色名的下拉框, 并且使用对应的颜色作为每一项的背景色.
QComboBox后台使用了Model, 因此, 我们设置其Qt::DecorationRole来产生颜色效果.
1234567891011121314151617181920212223242526272829303132333435363738class ColorListEditor : public QComboBox{ Q_OBJECTpublic: ColorListEditor(QWidget *widget=nullptr); QColor color() const; ...
Qt中的动态布局
在特定的情况下, 我们需要显示/隐藏窗口的某一部分, 从而要求窗口的尺寸也随之变化. 如果仅仅是简单地hide()和show(), 实现扩展是没问题的, 但是却不会自动收缩. 如果准确的自动收缩/扩展窗体的尺寸, 尤其是我们不应该固定尺寸, 而是应该随着控件的多少来动态调整?
这个涉及到几个函数和方法的使用.
将界面使用大的容器进行划分. 比如GroupBox, Widget等. 这样, 整个窗体是由这些顶层容器组成的, 我们可以通过计算这些顶层容器的尺寸来计算出最终的尺寸来. 而这些顶层容器, 划分的原则是, 显示/隐藏应该是在它们的粒度上进行的(这里指的是影响窗体尺寸的显示和隐藏. 如果不影响, 则没有这个约束. )
使用方法sizeHint()来获取每个容器的尺寸.
然后, 就可以使用顶层窗体的resize()函数来更改大小了.
最后, 注意一些SizeConstaint类函数的取值. 例如, Layout::setSizeConstraint(), 初始化时使用QLayout::SetMinimumSize作为参数, 当需要调整时, 按照这 ...