好工具推荐系列:Win10开源管理工具PowerToys

PowerToys 是一款实用工具的集合,它并不是新事物,Windows 95 就曾有过这款工具,只是 Windows 在原来的启发之下开发了这款针对 Window 10 系统更加高效的版本。目前 PowerToys 包括如下 7 项功能,每一项都非常实用,它们分别是:FancyZones:是一项用于设置和调整桌面窗口布局的功能。File Explorer Add-ons:是一项用于增强文件管理器的功能,目前只有预览窗口功能,而且这是现有系统本身具有的功能。Image Resizer:是一项能够快速修改图像尺寸的功能,它不仅能够修改单张图像尺寸,还可以批量修改多张图像尺寸。Keyboard Manager:是一项用于修改键盘映射的功能。PowerRename:是一项很强大的批量重命名功能。PowerToys Run:一项类似于 macOS 下聚焦搜索的启动 + 搜索的功能。Shortcut Guide:是一项显示 Windows 快捷键指南的功能。https://github.com/microsoft/PowerToys

Halcon标定系列(3):我个人总结的“眼在手外“和“眼在手上”的心得笔记

尊重作者,支持原创,如需转载,请附上原地址:https://libaineu2004.blog.csdn.net/article/details/106995624心得笔记字面意思,眼代表眼睛,这里指的是我们的工业相机;手,指的是我们的运动部分,比如机械手或者运动控制系统;眼在手上,就是相机按照在运动轴上面,跟随运动的某个轴一起运动,这种标定就是图像和机械点一一运动去做标定。眼在手外,就是相机固定一个位置拍照,机械手或者运动部分不会带动相机,这个时候标定就要一次性拍全视野,然后机械部分再一一针对图像的上点做好对应关系,然后标定。这两种标定是我们图像和运动部分联合主要的两种标定方法,都可以实现图像转机械运动,就是标定关系不一样而已,结果都是一样的!眼在手上就是一个点对应一个机械坐标,做九组就好了!也就是相机一次拍9个点 然后机械手走这九个点得到九个对应的机械坐标进行变换。眼在外:相机放置一个固定的位置,与机器人基坐标系相对位置不变眼在手:相机和机器手绑定在一个位置,机器手移动,相机也跟着移动halcon手眼标定,最少4点就可以,4个像素坐标对应4个机械手坐标就可以算出转换关系九点标定法的实现流程STEP 1:准备好一张标定板,里面有3X3的圆。STEP 2:把标定板水平放置在相机正下方,控制相机拍照得到一张图片,并按顺序(走Z字型)记录图片上9个圆的中心位置。STEP 3:控制机器人TCP工具末端按顺序(走Z字型)移动到每个圆心,并记录下9组机器人位置坐标数据。STEP 4: 执行标定,这里使用HALCON标定算子作为演示,利用上面求得的数据。图像上9个位置image_x:=[]image_y:=[]机器人9个位置robot_x:=[]robot_y:=[]图像与机器人数据结合vector_to_hom_mat2d (image_x, image_y, robot_x, robot_y, HomMat2D)矩阵进行保存:write_tuple (HomMat2D, '路径') 。注意:保存的矩阵后缀名是.tup格式的STEP 5:标定完成后,拍摄一个特征点的,求得像素位置img_x:=img_y:=利用以下算子即可把像素坐标转换成机器人坐标read_tuple (‘路径’, HomMat2D)affine_trans_point_2d(HomMat2D,img_x,img_y, Qx, Qy)到这里标定以及转换过程就完成了。read_image (Image, 'D:/hellowprld/初学者必用10mm视觉标定板图/9points.jpg') dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image) binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold) connection (Region, ConnectedRegions) *筛选出来九个点 select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 1000, 2000) shape_trans (SelectedRegions, RegionTrans, 'outer_circle') *求出九点坐标 area_center (RegionTrans, Area, Row, Column) disp_message (WindowHandle, 'R:'+Row+' C:'+Column, 'Image', Row, Column, 'black', 'true') *把求得的Row和Column赋值 *九点标定行 PxRow:=Row *九点标定列 PxColunm:=Column *九点标定行 *PxRow:=[23.5, 23.5, 23.5, 71.5, 71.5, 71.5, 118.5, 118.5, 118.5] *九点标定列 *PxColunm:=[28.5, 75.5, 122.5, 28.5, 75.5, 122.5, 28.5, 75.5, 122.5] *机器坐标行 Qx:=[100,50,0,100,50,0,100,50,0] *机器坐标列 Qy:=[0,0,0,50,50,50,100,100,100] *拿到机器坐标和像素坐标求出关系矩阵 * 标定行 标定列 机器X 机器Y 得到矩阵 vector_to_hom_mat2d (PxRow, PxColunm, Qx, Qy, HomMat2D) *保存矩阵 write_tuple (HomMat2D, '九点标定.tup') *读取矩阵 read_tuple ('九点标定.tup', HomMat2D) *利用求出来的物体行列坐标得到机器坐标 affine_trans_point_2d (HomMat2D, Row, Column, Qx1, Qy1)·官方例程vector_to_hom_mat2dcalibrate_hand_eye_scara_stationary_cam_approxhand_eye_stationarycam_calibrationpick_and_place_scara_stationary_cam参考文献关于“眼在手外“和“眼在手上”标定求教https://www.51halcon.com/forum.php?mod=viewthread&tid=4231【3】机器人手眼标定:固定向下相机https://www.51halcon.com/forum.php?mod=viewthread&tid=4271“眼在手中”标定之坐标转换https://www.51halcon.com/forum.php?mod=viewthread&tid=4265机器人手眼标定算法源码http://www.ihalcon.com/read-9533.html机械手手眼标定/9点标定/4点标定/Halcon标定脚本http://www.ihalcon.com/read-10022.htmlvb.net联合halcon以及运动控制卡做的点胶贴合项目http://www.ihalcon.com/read-14513.html手眼标定----眼在手外(eye-to-hand) [魁拔之十万火急]http://www.ihalcon.com/read-13820.html手眼标定----眼在手上(eye-in-hand) [魁拔之十万火急]http://www.ihalcon.com/read-14658.htmlhttp://www.ihalcon.com/read-14687.html九点标定-眼在外(没有标定板的情况) [魁拔之十万火急]http://www.ihalcon.com/read-14564.html手眼标定----眼在手上(eye-in-hand) [tystq]http://www.ihalcon.com/read-14209.html枫痕机械手相机9点坐标标定-基于C#+EmguCVhttps://www.cnblogs.com/thebreeze/p/10316030.html相机标定助手代码http://www.ihalcon.com/read-11647.htmlHaclon代码框架c#编程haclon代码学习http://www.ihalcon.com/read-14257.html

Halcon图像灰度取反

灰度线性变换*图像取反invert_image (GrayImage, ImageInvert)*增加对比度emphasize (ImageInvert, ImageEmphasize, Width, Height, 1)*减小对比度scale_image (ImageEmphasize, ImageScaled, 0.5, 0)*增加亮度scale_image (ImageScaled, ImageScaled1, 1, 100)*减小亮度scale_image (ImageScaled1, ImageScaled2, 1, -100)灰度非线性变换*1.对数变换log_image (GrayImage, LogImage, 'e')*2.指数变换pow_image (GrayImage, PowImage, 2)

Halcon标定系列(2):使用Halcon算子制作标定板

gen_caltab (7, 7, 0.01, 0.5, 'd:\\caltab.descr', 'd:\\caltab.ps')1、算子说明:标定板的点阵是7*7的,每个黑色圆点之间的间距MarkDist是0.01米,圆点直径与每个点之间距离的比值DiameterRatio为0.5。就是说,圆点的直径是0.01*0.5m。最后两个参数是文件输出。caltab.ps文件可以用 Photoshop打开。2、宽和高width=(Xnum+1)*MarkDist*1000height=(Ynum+1)*MarkDist*1000另一个算子:create_caltab---参考文献https://www.cnblogs.com/al-meno/p/5606665.html偶然发现除了这个GSView以外,Adobe的Acrobat Distiller也可以打印这个.ps文件。https://www.51halcon.com/forum.php?mod=viewthread&tid=1214

min-height:15px; border-radius:5px; background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E1E4E6,stop:1 #CCD3D9); .QPushButton:hover,.QToolButton:hover{ background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F3F4,stop:1 #E7E9EB); .QPushButton:pressed,.QToolButton:pressed{ background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #E1E4E6,stop:1 #CCD3D9); .QToolButton::menu-indicator{ image:None; QToolButton#btnMenu,QToolButton#btnTool,QPushButton#btnMenu_Min,QPushButton#btnMenu_Max,QPushButton#btnMenu_Close{ border-radius:3px; color:#000000; padding:3px; margin:0px; background:none; border-style:none; QToolButton#btnMenu:hover,QPushButton#btnMenu_Min:hover,QPushButton#btnMenu_Max:hover{ color:#FFFFFF; margin:1px 1px 2px 1px; background-color:rgba(51,127,209,230); /*QToolButton#btnTool:hover{ color:#FFFFFF; margin:1px 1px 2px 1px; background-color:rgba(51,127,209,230); QToolButton#btnTool:hover{ /*鼠标放上后*/ color:rgb(255, 255, 255); min-height:20; border-style: solid; border-top-left-radius:2px; border-top-right-radius:2px; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 rgb(226,236,241), stop: 0.3 rgb(160,160,160), stop: 1 rgb(120,120,120)); border:1px; border-radius:5px; padding:2px 4px; QToolButton#btnTool:pressed{ /*按下按钮后*/ color:rgb(255, 255, 255); min-height:20; border-style:solid; border-top-left-radius:2px; border-top-right-radius:2px; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 rgb(226,236,241), stop: 0.3 rgb(190,190,190), stop: 1 rgb(160,160,160)); border:1px; border-radius:5px; padding:2px 4px; QToolButton#btnTool:checked{ /*选中后*/ color:rgb(255, 255, 255); min-height:20; border-style:solid; border-top-left-radius:2px; border-top-right-radius:2px; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 rgb(226,236,241), stop: 0.3 rgb(190,190,190), stop: 1 rgb(160,160,160)); border:1px; border-radius:5px; padding:2px 4px; QMenu::icon:checked {    background: #a3d1ff;    border: 1px solid #3399ff;    position: absolute;    top: 1px;    right: 1px;    bottom: 1px;    left: 1px;}

QString格式化的几种用法:补零/进制转换/保留小数位等

QString QString::arg(long a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) constQString QString::arg(int a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const1、QString格式化arg前面自动补0int seconds = m_calc.elapsed() / 1000; int hour = int(seconds / 3600); int min = int((seconds - hour * 3600) / 60); int sec = seconds % 60; //QString格式化arg前面自动补0 QString str = QString("%1:%2:%3").arg(hour, 2, 10, QLatin1Char('0')).arg(min, 2, 10, QLatin1Char('0')).arg(sec, 2, 10, QLatin1Char('0')); QStringList list; list << tr("%1").arg(hour) << tr("%1").arg(min) << tr("%1").arg(sec); int val = 16; QString str = QString("%1").arg(val & 0xFF, 2, 16, QLatin1Char('0')); //0016 QString str = QString("%1").arg(val, 4, 10, QLatin1Char('0')); //4代表宽度,10表示10进制,空位补零2、进制转换QString ss = QString("十进制64转为十六进制%1").arg(64, 0, 16);//0代表宽度,16表示16进制,空位补零3、数字转QString,并保留小数点位数//整数转QStringint num1=123;QString str1 = QString::number(num1);qDebug()<<"str1:"<<str1<<endl;//小数转QString,保留两位小数double num2 = 123.456789;QString str2=QString::number(num2,'f',2);qDebug()<<"str2:"<<str2<<endl;4、数字转QString,使用asprintfui->comboBox_pulse->addItem(QString::asprintf("%d", PULSE_LOW));ui->lineEdit_x->setText(QString::asprintf("%.3f", m_stuMotionPos.X));5、QString中的arg还可以对浮点类型的数字按照一定的精度来转换QString QString::arg(double a, int fieldWidth = 0, char format = 'g', int precision = -1, QChar fillChar = QLatin1Char(' ')) constFormat Meaninge      format as [-]9.9e[+|-]999E      format as [-]9.9E[+|-]999f      format as [-]9.9g      use e or f format, whichever is the most conciseG      use E or f format, whichever is the most conciseQString ss = QString("delta %1").arg(123.45678, 0, 'g', 6);结果是ss="delta 123.456"。浮点类型格式化为只显示六位有效数字,并且是采用四舍五入的方式。6、QString/string/wstring的转换QString::fromStdString()QString::fromStdWString()str.toStdString()QObject::tr("位置超出范围").toStdWString()

如何有效禁止qDebug的输出?

一、Release如何禁用在.pro文件加入以下语句:#Release禁止输出qWarning/qDebug信息CONFIG (release, debug|release) {DEFINES += QT_NO_WARNING_OUTPUTDEFINES += QT_NO_DEBUG_OUTPUT}但是还不够,需要把工程清理,重新构建才能生效!!二、qDebug如何使用qDebug用于在控制台输出调试信息,主要有以下几种用法。1、类似c++的cout函数QString str="world";qDebug()<<"hello "<<str<<"!"<<endl;注:此处endl起到的作用有两个:a、等同于\n换行b、刷新缓冲区,将缓冲区数据写入文件或屏幕,因此会影响程序效率。endl等价于"/n"+flush();2、构造函数直接引入参数字符串拼接QString str="world!";qDebug("hello "+str);类似mfc中CString的format函数int year=18;qDebug("今年我%d",year);注:%a,%A 读入一个浮点值(仅C99有效)    %c 读入一个字符    %d 读入十进制整数    %i 读入十进制,八进制,十六进制整数    %o 读入八进制整数    %x,%X 读入十六进制整数   %s 读入一个字符串,遇空格、制表符或换行符结束。    %f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入。    %p 读入一个指针    %u 读入一个无符号十进制整数   %n 至此已读入值的等价字符数    %[] 扫描字符集合    %% 读%符号

总结一下Qt内存泄漏检测与处理策略,并附个人写的C++单例类,用于内存自动释放

如果时间急迫,不想看完整文章,可以直接去到文章末尾,看结论。有我个人写的C++单例类,用于内存自动释放。1、QtCreator编写C++代码,怎么检测内存泄漏?请参见本人的另一篇博文:https://blog.csdn.net/libaineu2004/article/details/1040716272、Qt中控件new之后需不需要delete的问题https://blog.csdn.net/Aidam_Bo/article/details/86303096 * QT的父子对象机制是在 QWidget和QOject中实现的。当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象,然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除。 * 这种父子对象机制会在很大程度上简化我们的内存管理工作,减少内存泄露的风险。 * 我们需要显式删除(就是用Delete删除)的对象是那些使用new创建的并且没有父对象的对象(切记是new的才要delete, * 通过成员函数获得的对象,没有特殊说明的,千万不要随便delete。 * 如果我们在删除一个对象的父对象之前删除它,QT会自动地从它的父对象的子对象列表中移除它的。 * Qt自动回收不像Java这种,有垃圾回收机制。 * Qt自动回收是靠父子关系。父亲销毁了。他的孩子也销毁。 * 所以为什么main函数里面main widget/dialog/mainWindow是分配在栈上的原因。 * 其他new出来的东西都以这个widget作为父亲。 当程序最后结束了,main widget弹栈。 * 父类被销毁。子类跟着被销毁。 所以你自己new出来的控件,如果没有父类,自己又不删除,那就会造成内存泄漏。小结--Qt的半自动化的内存管理:(1)QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象。(2)QWidget及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位(当close时会析构该对象)。(3)QAbstractAnimation派生类的对象,可以设置 QAbstractAnimation::DeleteWhenStopped。(4)QRunnable::setAutoDelete()、MediaSource::setAutoDelete()。(5)父子关系:父对象、子对象、父子关系。这是Qt中所特有的,与类的继承关系无关,传递参数是与parent有关(基类、派生类,或父类、子类,这是对于派生体系来说的,与parent无关)。3、Qt智能指针和QObject对象树系统(父子系统)结合使用出现的问题https://blog.csdn.net/gamesdev/article/details/8724090 * 首先要弄明白为什么qt只new不delete,父子对象管理模式先弄清楚,另外QScopedPoint有个接口data,返回正在管理的原始指针。 * QObject自有对象树系统(父子系统),它在和其它QObject子类进行交互的时候会将对方的指针保存起来,形成父子关系, * 最终一个QObject子类指针会形成一个强大的树状结构,当父亲销毁的时候,会先销毁它的孩子(如果它的孩子是通过new操作符在堆上创建的话)。但是智能指针在保有QObject子类的时候会自动调用它的析构函数,从而引起事实上的两次delete,这个时候编译器的就会报错。 * 那我熟悉的QScopedPointer来说,本来将它用在类的成员中是一个很好的选择,但是由于它保有的是QObject的子类,这个智能指针在和其它QObject子类交互的时候难免会被对方保有原始指针的值,在进入类的析构函数,QScopedPointer保有原始指针的值会被先于释放并置为“已删除”的值0xfeeefeee,这个时候再通过智能指针的自动清理只可能会带来运行错误。在qscopedpointer.h源码中,我们看到QScopedPointerDeleter类的cleanup静态函数并不带有在delete之前的指针的值检测,于是在delete一个无效的指针时,错误发生了。4、为什么官方的Qt示例和教程不使用智能指针?目前得出了一个结论:只要加入了QObject对象树系统(父子机制),那么内存管理不是你的事儿了,你也不应该管,也不应该让智能指针管。 * 智能指针类std::unique_ptr和std::shared_ptr是内存管理。拥有这样一个智能指针意味着,你拥有指针。 * 但是,在QObject使用QObject父级创建或派生类型时,所有权(清理责任)将交给父级QObject。 * 在这种情况下,标准库智能指针是不必要的,甚至是危险的,因为它们可能会导致双重删除。 * 然而,当一个QObject在堆上创建而没有父类时,QObject情况就非常不同。在这种情况下,你不应该只保存一个原始指针, * 而是一个智能指针,最好是一个std::unique_ptr对象。这样你就可以获得资源安全。 * 如果你稍后将对象所有权交给QObject你可以使用的父项std::unique_ptr<T>::release(),如下所示: * auto obj = std::make_unique<MyObject>(); * // ... do some stuff that might throw ... * QObject parentObject; * obj->setParent( &parentObject ); * obj.release();5、qDeleteAll与clearhttps://blog.csdn.net/yao5hed/article/details/81092139typedef struct _Defs int a; double d; QString s; } Def; QList<Def*> defs; for(int i=0;i<500000;i++) Def* dd = new Def; dd->a = 12; dd->d = 4.23; dd->s = "jda"; defs.append(dd); qDebug()<<"before qDeleteAll: "<<defs.size(); qDeleteAll(defs); qDebug()<<"after qDeleteAll: "<<defs.size(); defs.clear();运行结果发现,不调用qDeleteAll的情况下,程序占内存78M;加上之后,只占内存12M。但是前后的size没有变化。当T的类型为指针时,调用clear方法能置空,但并不能释放其内存。qDeleteAll可以释放容器元素内存,但没有对容器的置空操作,也就是size没变。所以qDeleteAll之后必须加上clear方法。6、deleteLaterhttps://blog.csdn.net/yao5hed/article/details/81092168void QObject::deleteLater() QCoreApplication::postEvent(this, new QDeferredDeleteEvent()); bool QObject::event(QEvent *e) switch (e->type()) { ...... case QEvent::DeferredDelete: qDeleteInEventHandler(this); break; void qDeleteInEventHandler(QObject *o) delete o; }Qt中不建议手动delete掉QObject对象。原因一:不注意父子关系会导致某个对象析构两次,一次是手动析构,还有一次是parent析构,后者可能会出现delete堆上的对象。delete是C++和QT共有的一个操作符即时使用实时就析构删除了,而Qt里的deletelater的原理是:QObject::deleteLater()并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象。 这样做的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时。应用例子:父窗体的子窗体在focusoutevent时deletelater();然后在主窗体绑定信号子窗体的destroy()信号和父窗体的槽函数,然后在槽函数中象父窗体调用父窗体的接口函数向父窗体发送子窗体的文本text();7、QObjectCleanupHandlerhttps://blog.csdn.net/yao5hed/article/details/81092178https://blog.csdn.net/luoyayun361/article/details/97250027#include <QObjectCleanupHandler> m_pCleanupHandler = new QObjectCleanupHandler(); m_pObj1 = new CObject(); m_pObj2 = new CObject(); m_pObj3 = new CObject(); m_pCleanupHandler->add(m_pObj1); m_pCleanupHandler->add(m_pObj2); m_pCleanupHandler->add(m_pObj3); //最后只需要调用 m_pCleanupHandler->clear();所有的对象都会全部释放。并且,如果其中有些对象已经在别的地方进行释放, 那就会自动从QObjectCleanupHandler管理列表中自动删除,不会重复删除。所以,即便是重复调用clear()也不会出问题。使用QObjectCleanupHandler进行资源管理非常方便。x1、结论1、QObject及其派生类的对象,如果其parent非0,那么其parent析构时会析构该对象。我们不必手动删除内存。2、程序员自己new出来的QObject及其派生类的对象,如果没有父类,自己又不删除,那就会造成内存泄漏。怎么办?我们可以使用QObjectCleanupHandler的机制来管理内存,在应用程序结束之前释放它们。附上我写的单例类:autocleanuphandler.h#ifndef CAUTOLEANUPHANDLER_H #define CAUTOLEANUPHANDLER_H #include <QGlobalStatic> #include <QObjectCleanupHandler> #define AUTOCLEANUPHANDLER CAutoCleanupHandler::instance() class CAutoCleanupHandler public: CAutoCleanupHandler() {} virtual ~CAutoCleanupHandler() {} public: static CAutoCleanupHandler *instance(); public: QObject *add(QObject *object); void remove(QObject *object); bool isEmpty() const; void clear(); private: QObjectCleanupHandler m_cleanupHandler; #endif // CAUTOLEANUPHANDLER_H autocleanuphandler.cpp #include "autocleanuphandler.h" Q_GLOBAL_STATIC(CAutoCleanupHandler, clean) CAutoCleanupHandler *CAutoCleanupHandler::instance() return clean(); QObject *CAutoCleanupHandler::add(QObject *object) return m_cleanupHandler.add(object); void CAutoCleanupHandler::remove(QObject *object) m_cleanupHandler.remove(object); bool CAutoCleanupHandler::isEmpty() const return m_cleanupHandler.isEmpty(); void CAutoCleanupHandler::clear() m_cleanupHandler.clear(); }使用举例://新建控件,无父类FormOptionsWorkpiece *workpiece = new FormOptionsWorkpiece();FormOptionsMotionctrlcard *motionctrlcard = new FormOptionsMotionctrlcard();FormOptionsMachinetool *machinetool = new FormOptionsMachinetool();FormOptionsCameraInstall *camerainstall = new FormOptionsCameraInstall();//添加内存对象AUTOCLEANUPHANDLER->add(workpiece);AUTOCLEANUPHANDLER->add(motionctrlcard);AUTOCLEANUPHANDLER->add(machinetool);AUTOCLEANUPHANDLER->add(camerainstall);//exe退出前,自动清理内存AUTOCLEANUPHANDLER->clear();x2、参考文献Qt浅谈之一:内存泄露(总结)https://blog.csdn.net/taiyang1987912/article/details/29271549https://www.cnblogs.com/lsgxeva/p/7811288.htmlQt父子对象内存管理实现简析https://www.dushibaiyu.com/2014/07/qt-fuzi-neicun.htmlQt智能指针官方文档https://doc.qt.io/qt-5/qsharedpointer.htmlhttps://doc.qt.io/qt-5/qscopedpointer.htmlhttps://doc.qt.io/qt-5/qobjectcleanuphandler.html

好工具推荐系列:Python IDE之PyCharm/Spyder/Jupyter/Eric

IDE流行度KDnuggets2018年的一个博客发起了一项投票:数据科学中最好用的Python IDE是什么?本次调查共有1900多人参与,调查结果如下图所示。前5个选择是:Jupyter,57%PyCharm,35%Spyder,27%Visual Studio Code,21%Sublime Text,12%IDE用途如果是web开发或大工程,建议使用PyCharm;如果是数据处理,建议Spyder;Spyder是使用PyQt开发的GUI。而Jupyter Notebook 已迅速成为数据分析,机器学习的必备工具。因为它可以让数据分析师集中精力向用户解释整个分析过程。Jupyter这个名字是它要服务的三种语言的缩写:Julia,Python和R,这个名字与“木星(jupiter)”谐音。IDE官网1.SpyderSpyder是Python(x,y)的作者为它开发的一个简单的集成开发环境。和其他的Python开发环境相比,它最大的优点就是模仿MATLAB的“工作空间”的功能,可以很方便地观察和修改数组的值。Spyder最大的亮点就是拥有和Matlab/Rstudio类似的workspace的区域,你可以轻松查看到所有你定义的变量,并可以交互式的点击修改,对于初学者来说是很能帮的上忙的功能。https://www.spyder-ide.org/https://github.com/spyder-ide/spyderhttps://pypi.org/project/spyder/2.JupyterJupyter Notebook 的本质是一个 Web 应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和 markdown。 用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等。https://github.com/jupyter/notebookhttps://github.com/jupyter/jupyter3.PycharmPyCharm 是 JetBrains 开发的 Python IDE。PyCharm用于一般IDE具备的功能,比如, 调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制……另外,PyCharm还提供了一些很好的功能用于Django开发,同时支持Google App Engine,更酷的是,PyCharm支持IronPython!https://www.jetbrains.com/pycharm/4.EricEric 是全功能的 Python 和 Ruby 编辑器和 IDE,是使用 Python 编写的。Eric 基于跨平台的 GUI 工具包 Qt,集成了高度灵活的 Scintilla 编辑器控件。Eric 包括一个插件系统,允许简单的对 IDE 进行功能性扩展。Eric的功能与其他IDE类似:支持匹配,代码完成,类浏览器,集成单元测试等。它还具有Qt表单预览功能,如果您为应用程序开发Qt GUI,这很有用。PyQt5与Eric6是众所周知的Python平台下用来快速开发GUI程序的绝配,因此Eric也是PyQt官方推荐的IDE。http://eric-ide.python-projects.org/https://hg.die-offenbachs.homelinux.org/erichttps://sourceforge.net/projects/eric-ide/files/eric6/引申阅读1、Python非官方发行版Python(x,y):GUI基于PyQt,曾经是功能最全也是最强大的,而且是Windows系统中科学免费Python发行版的不二选择。不过今时已不同往昔,如今版本较为老旧,跟不上时代了。不推荐!https://sourceforge.net/projects/python-xy/WinPython:功能也是比较全的,软件包比较新,GUI基于PyQt,不过相对于Python(x,y),它主要是关注便携式安装体验:你可以把它装在u盘里面。局限于Windows平台,不能跨平台。Python(x,y)和WinPython都是开源项目,其项目负责人都是Pierre Raybaut。按Pierre自己的说法是“WinPython不是试图取替Python(x,y),而是出于不同动机和理念:更灵活、易于维护、可移动、对操作系统侵略性更小,但是用户友好性更差、包更少、没有同Windows资源管理器集成。”。此外Python(x,y)不是很稳定,此外看它目前的更新不是很频繁,确实有可能Pierre后来的工作重心放在WinPython上了。http://winpython.github.io/https://sourceforge.net/projects/winpython/Anaconda:Anaconda是Python科学技术包的合集,功能和Python(x,y) 类似。这个是新起之秀。包管理使用conda,GUI基于PySide,所有的包基本上都是最新版,没有PyQt和wxpython等,容量适中,但该有的科学计算包都有:numpy,sicpy,matplotlib,spyder.....比如Linux系统里面,Anaconda安装、更新和删除都很方便,且所有的东西都只安装在一个目录中/home/wxp/anaconda/。Anaconda的开发和维护中有Python创始人和社区的核心成员,可以想象这个发行包肯定会"后来居上"!因此在各种操作系统中,无论是Linux,还是Windows,又或是Mac,我都强烈推荐Anaconda。因为从软件的美观程度,版本兼容性,更新频率,管理难易程度,综合考虑,还是建议选择Anaconda。Anaconda,傻瓜式安装,一键配置好Python环境以及一些常用第三方库,并自带Notebook和Spyder。新手我强烈建议你在安装Anaconda后使用Notebook来执行代码,因为对于初学者来说最重要的就是反馈,在Notebook中一行命令一行结果。所有结果都会保存方便回头Check,并且页面没有太多的插件/按钮,十分简洁。对于做数据分析可视化简直不要太舒服,并且还有很多Magic命令!https://www.anaconda.com/https://www.anaconda.com/products/individual Individual Edition下载,网页拉到最底部https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 清华镜像,推荐教程《完美安装 Anaconda3 + PyQt5 + Eric6》https://blog.csdn.net/weiaitaowang/article/details/52045360教程《血泪安装 Anaconda3 + PyQt5 + Eric6》https://blog.csdn.net/weixin_41965380/article/details/84034526firecat本人也写了一篇安装教程:https://libaineu2004.blog.csdn.net/article/details/1077383472、Octave是什么?Octave是一种编程语言,旨在解决线性和非线性的数值计算问题。Octave为GNU项目下的开源软件,早期版本为命令行交互方式,4.0.0版本发布基于QT编写的GUI交互界面。Octave语法与Matlab语法非常接近,可以很容易的将matlab程序移植到Octave。同时与C++,QT等接口较Matlab更加方便。http://www.gnu.org/software/octave/3、Pyside2 vs PyQt5https://www.riverbankcomputing.com/ PyQt官网https://doc.qt.io/qtforpython/ Pyside2官方手册https://pypi.org/project/PyQt5/https://pypi.org/project/PySide2/qtpy项目提供统一的层以通过单个代码库支持PyQt5,PySide2,PyQt4和PySidehttps://github.com/spyder-ide/qtpyhttps://machinekoder.com/pyqt-vs-qt-for-python-pyside2-pyside/

好教程推荐系列:简明Python教程/Python进阶/Think Python 2e/Python 黑魔法指南/PyCharm 中文指南

0.Python官方中文文档https://docs.python.org/zh-cn/3/1. 《简明Python教程》中文版https://github.com/LenKiMo/byte-of-pythonhttps://github.com/swaroopch/byte-of-pythonhttps://python.swaroopch.com/2. 《Python进阶》中文版https://github.com/eastlakeside/interpy-zhhttp://interpy.eastlakeside.com/3. 《Think Python 2e》中文版https://github.com/bingjin/ThinkPython2-CNhttps://codingpy.com/books/thinkpython2/4.《Python之路V2.0》公众号:Python小例子5.从零开始学Python《Python - 100天从新手到大师》https://github.com/jackfrued/Python-100-Days《Python语言基础50课》https://github.com/jackfrued/Python-Core-50-Courses6.《Python 黑魔法指南》https://github.com/iswbm/magic-python7.《PyCharm 中文指南》https://github.com/iswbm/pycharm-guide8.《Python知识手册》https://github.com/liyangbit/Python-Knowledge-Handbook来自weChat号:Python数据之道9.《Effective Python:编写高质量Python代码的90个有效方法(原书第2版)》作者:[美]布雷特·斯拉特金(Brett Slatkin)出版社:机械工业出版社出版时间:2021年02月x.AI换脸https://github.com/iperov/DeepFaceLab

Halcon找圆系列(3)找金属表面的圆孔

我在Halcon学习网发了一个帖子:请教工件的金属表面圆孔的识别与定位http://www.ihalcon.com/read-15016-1.html解决方案有了,源码如下:dev_update_off () dev_close_window () read_image (Image, 'D:/pic/202006042055044969.jpg') *彩色转灰度图 count_channels (Image, Channels) if (Channels == 3) rgb1_to_gray (Image, Image) *真彩色转灰度图 elseif (Channels == 4) decompose4 (Image, ImageR, ImageG, ImageB, ImageA) compose3 (ImageR, ImageG, ImageB, MultiChannelImage) rgb1_to_gray (MultiChannelImage, Image) endif *获取图像宽高 get_image_size (Image, Width, Height) dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_display (Image) *动态二值化 D := 30 mean_image(Image, Mean, D*2+1, D*2+1) dyn_threshold(Image, Mean, Seg, 5, 'dark') fill_up(Seg, SegFillUp) connection(SegFillUp, segConnect) select_shape(segConnect, SelectedRegions, ['area','circularity'], 'and', [500, 0.7], [20000, 1]) *求出最小外接圆的半径和中心点 smallest_circle(SelectedRegions, Row, Column, Radius) *求出圆的面积和中心点 area_center(SelectedRegions, Area, Row1, Column1) dev_display(Image) gen_circle(Circles, Row, Column, Radius) dev_display(Circles) *数量统计 count_obj(SelectedRegions, Number) if (Number < 1) disp_message (WindowHandle, '未找到', 'window', 12, 12, 'black', 'true') return() endif *结果显示 for i:=1 to Number by 1 select_obj (SelectedRegions, ObjectSelected, i) r := Row[i - 1] c := Column[i - 1] rds:= Radius[i - 1] disp_message (WindowHandle, '圆心:Row:'+ r + ' Col:' + c, 'window', 12, 12, 'black', 'true') disp_message (WindowHandle, '半径:'+ rds, 'window', 52, 12, 'black', 'true') endfor stop()另外也可以尝试使用形状匹配,匹配之前进行一下预处理,可以让图像变化不那么明显,看上去更稳定一些。Illuminate:图像照亮EquHistoImage:直方图均衡化*图像预处理/均衡 Mask := 31 illuminate (Image, Image, Mask, Mask, 0.7) equ_histo_image (Image, Image) *图像预处理/动态二值化 D := 30 mean_image(Image, Mean, D*2+1, D*2+1) dyn_threshold(Image, Mean, Seg, 5, 'dark') fill_up(Seg, SegFillUp) connection(SegFillUp, segConnect) *使用面积阈值,过滤掉一部分干扰物 select_shape (segConnect, SelectedRegions, 'area', 'and', 3000, 10000) region_to_bin(SelectedRegions, Binary, 0, 255, Width, Height) Image := Binary---参考官方例程smallest_circle.hdevmeasure_ring.hdevdyn_threshold.hdevball.hdev

好工具推荐系列:JetBrains Mono字体

字体下载https://www.jetbrains.com/lp/mono/字体安装Unzip the archive and install the font:macOSSelect all font files in the folder and double-click them. Click the “Install Font” button.WindowsSelect all font files in the folder, right-click any of them, then pick “Install” from the menu.LinuxUnpack fonts to ~/.local/share/fonts (or /usr/share/fonts, to install fonts system-wide) and execute fc-cache -f -v

C++ list,怎么交换任意两个元素的位置?

方法1:顺序遍历list与vector不同,不支持随机访问和数组下标访问。int start = 0, end = 2;//需要交换的两个元素位置 CadEntities *p = CADSHAREDDATA->getCadEntities(); list<list<CadPolyline>>::iterator iter1; list<list<CadPolyline>>::iterator iter2; list<CadPolyline> temp; int k = 0; for (list<list<CadPolyline>>::iterator iter = p->_polylines.begin(); iter != p->_polylines.end(); ++iter, ++k) //遍历 if (k == start) iter1 = iter; if (k == end) iter2 = iter; //交换值 temp = *iter1; *iter1 = *iter2; *iter2 = temp;方法2:借助迭代器函数STL 中有用于操作迭代器的三个函数模板,它们是:advance(p, n):使迭代器 p 向前或向后移动 n 个元素。distance(p, q):计算两个迭代器之间的距离,即迭代器 p 经过多少次 + + 操作后和迭代器 q 相等。如果调用时 p 已经指向 q 的后面,则这个函数会陷入死循环。iter_swap(p, q):用于交换两个迭代器 p、q 指向的值。#include <list> #include <iostream> #include <algorithm> //要使用操作迭代器的函数模板,需要包含此文件 using namespace std; int main() int a[5] = { 1, 2, 3, 4, 5 }; list <int> lst(a, a+5); list <int>::iterator p = lst.begin(); advance(p, 2); //p向后移动两个元素,指向3 cout << "1)" << *p << endl; //输出 1)3 advance(p, -1); //p向前移动一个元素,指向2 cout << "2)" << *p << endl; //输出 2)2 list<int>::iterator q = lst.end(); q--; //q 指向 5 cout << "3)" << distance(p, q) << endl; //输出 3)3 iter_swap(p, q); //交换 2 和 5 cout << "4)"; for (p = lst.begin(); p != lst.end(); ++p) cout << *p << " "; return 0; }程序的输出结果是:1) 32) 23) 34) 1 5 3 4 2

C++开源游戏推荐,EA部分开源红色警戒1

声明:项目非本人原创,仅仅分享链接!EA部分开源红警5 月 27 日,知名游戏公司 EA 在 GitHub 上搞了个大新闻,把《命令与征服》系列中的 2 个游戏的部分源码开源了!这两个游戏分别是:Tiberian Dawn(泰伯利亚的黎明) 和 Red Alert(红色警戒)。https://github.com/electronicarts/CnC_Remastered_Collection/推荐EA的几个开源C++库https://github.com/electronicarts/EAThreadhttps://github.com/electronicarts/EAStdChttps://github.com/electronicarts/EASTL EASTLEASTL EASTL详解https://github.com/microsoft/STL 微软STL

好工具推荐系列:UML绘图软件drawio(画流程图/框图/类图软件)

draw.io 是一个强大简洁的在线的绘图网站,支持流程图,UML图,架构图,原型图等图标。支持Github,Google Drive, One drive等网盘同步,并且永久免费。如果觉得使用Web版不方便,draw.io 也提供了多平台的离线桌面版可供下载。网页版https://app.diagrams.net/ 桌面版https://github.com/jgraph/drawio-desktophttps://github.com/jgraph/drawio-desktop/releases同类产品processonhttps://www.processon.com/

开源项目推荐:基于Qt开发的远程桌面监控和文件传输软件Aspia

官网start [Aspia]GitHub - dchapyshev/aspia: Remote desktop and file transfer tool.Index of /dev  已编译的第三方依赖库aspia/building.md at master · dchapyshev/aspia · GitHub 源码编译说明GitHub - SoftwareNetwork/binaries: Mirror of sw binaries from https://software-network.org/client/x86 or x86_64 CPU with SSE2Windows 7/2008 R2 or higher, Debian/Ubuntu Linux, MacOS X源码怎么编译?一、先要安装vcpkg这个工具1、官网下载最新版 Releases · microsoft/vcpkg · GitHub2、解压,然后双击执行\vcpkg-2021.05.12\bootstrap-vcpkg.bat,稍等一会,会生成vcpkg.exe3、cmd命令行执行vcpkg integrate installC:\Users\firecat>cd T:\tmp-source\aspia\vcpkg-2021.05.12 C:\Users\firecat>T: T:\tmp-source\aspia\vcpkg-2021.05.12>vcpkg integrate install Applied user-wide integration for this vcpkg root. All MSBuild C++ projects can now #include any installed libraries. Linking will be handled automatically. Installing new libraries will make them instantly available. CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=T:/tmp-source/aspia/vcpkg-2021.05.12/scripts/buildsystems/vcpkg.cmake" T:\tmp-source\aspia\vcpkg-2021.05.12>更多关于vcpkg的安装知识,详情见:vcpkg安装和使用--学习入门_你好,Albert的博客-CSDN博客_vcpkg安装4、VS2019需要安装英文语言包因为vcpkg的源码写的比较死板(部分路径都是写死的),导致该工具无法识别中文的开发环境。办法:VS2019菜单-工具-获取工具和功能二、想编译Aspia v2.1以上的源码,须知:1、cmkae版本必须在v3.20以上2、Qt版本必须在v5.14以上,否则会出现Unknown CMake command "qt5_import_plugins"的错误https://github.com/dchapyshev/aspia/issues/1083、openssl在1.0.x之前的版本中,文件为libeay32.dll和ssleay32.dll,在1.1.x之后的版本中,名字是libssl.dll和libcrypto.dll4、第三方库和依赖库都是32位的:vcpkg install   asio:x86-windows-staticvcpkg install   gtest:x86-windows-staticvcpkg install   libvpx:x86-windows-staticvcpkg install   libyuv:x86-windows-staticvcpkg install   openssl:x86-windows-staticvcpkg install   opus:x86-windows-staticvcpkg install   protobuf:x86-windows-staticvcpkg install   rapidjson:x86-windows-staticvcpkg install   rapidxml:x86-windows-staticvcpkg install   sqlite3:x86-windows-staticvcpkg install   libwebm:x86-windows-staticvcpkg install   zstd:x86-windows-static5、aspia_host_core必须是dll,要编译成动态库,而非静态库6、出现Could NOT find Protobuf (missing: Protobuf_PROTOC_EXECUTABLE)这个错误提示,怎么办?请看我的另一篇博文:Could NOT find Protobuf (missing: Protobuf_PROTOC_EXECUTABLE)_$firecat全宏的代码足迹$-CSDN博客x、cmake的选项源码有若干处需要调整1、qm路径C:\Users\Administrator\Desktop\aspia-master\source\qt_base\CMakeLists.txt删除file(GLOB QT_QM_FILES ${Qt5_DIR}/../../qt5/translations/*.qm)改为file(GLOB QT_QM_FILES ${Qt5_DIR}/../../../translations/*.qm)if(Qt5LinguistTools_FOUND)    # Get the list of Qt translation files.    #file(GLOB QT_QM_FILES ${Qt5_DIR}/../../qt5/translations/*.qm)    file(GLOB QT_QM_FILES ${Qt5_DIR}/../../../translations/*.qm)    add_qt_translations(aspia_qt_base QRC_FILE "qt_translations.qrc" QM_FILES ${QT_QM_FILES})else()    message(WARNING "Qt5 linguist tools not found. Internationalization support will be disabled.")endif()2、qrc资源文件C:\Users\Administrator\Desktop\aspia-master\source\qt_base\qt_translations.qrcC:\Users\Administrator\Desktop\aspia-master\x86\source\qt_base\qt_translations.qrc删除<file>qtbase_tr.qm</file>3、编译出错,如下,怎么办? 打开VS配置对话框,导入库里面,把*.dll文件去掉x、编译时,以下库需要重点关注,VS配置导入库时,需要指向它们D:\vcpkg\packages\libwebm_x86-windows-static\debug\lib\libwebmd.libD:\vcpkg\packages\libwebm_x86-windows-static\lib\libwebm.lib编译遗留问题Debug和Release都能顺利编译通过。但是Debug的生成的exe运行会报错。凡是源码有LOG(...)的语句,debug都过不了。

解决QDialogButtonBox按钮的英文翻译问题

问题:使用Qt Creator设计师,把QDialogButtonBox拖到界面上,显示3个标准按钮:“Ok”、“Cancel”和"Apply"运行,结果按钮显示英文。怎么让它们变中文呢?解决过程:复制qt_zh_CN.qm放入到工作目录下,使用QTranslator加载,QApplication.installTranslator(...).结果:无效。怎么办?解决办法:办法1、手动设置【推荐】//将buttonbox中的ok/cancel/apply变成中文 ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("确定")); ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("取消")); ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("应用"));办法2、在qt安装找到qt_zh_CN.ts,里面手动添加:<context> <name>QPlatformTheme</name> <message> <location filename="../src/widgets/qdialogbuttonbox.cpp" line="+42"/> <location line="+18"/> <source>OK</source> <translation>确定</translation> </message> <message> <location line="+54"/> <source>Cancel</source> <translation>取消</translation> </message> ..... </context>然后再生成qt_zh_CN.qm文件参考文献https://blog.csdn.net/qiuchengw/article/details/38821215

解决Qt问题:无法连接到进程内QML调试器

问题:由于在Qt5以上版本默认开启QML调试器造成的。用于告知用户,这将打开一个到运行QML的Javascript解释器的端口,以便从中获得调试输出。显然,这会造成一个安全漏洞,所以在不安全的地方使用时应该关闭它(在释放运行时自动关闭)。Qt4默认不开启QML调试器,而Qt5版本以上默认开启。如果您不使用QML,无论如何都要关闭它。由于开启QML调试需要在TCP端口打开套接字,这存在安全风险。Internet上的任何人都可以连接到正在调试和执行任何JavaScript函数的应用程序。因此,您必须确保端口受到防火墙的适当保护。解决办法1:去掉下图所示的Enable QML的勾选解决办法2:直接在pro文件关闭QML调试器:Qt4版本: CONFIG -= declarative_debugQt5版本: CONFIG -= qml_debug

Qt5.12.x怎么调试Qt的源码?

安装源码安装Qt的时候记得要勾选安装源码。配置QtCreator配置VS20171、鼠标点击在解决方案上,右键 –> 属性 –> 通用属性 –> 调试源文件,将源码所在目录包含进去即可。E:\software\Qt\Qt5.12.9\5.12.9\Src2、在断点处按 F11 即可进入源码3、VS主菜单->选项->调试->符号,添加Qt有关*.pdb文件的路径下载5.12.8调试信息(*.pdb文件)x64 MSVC2017Index of /online/qtsdkrepository/windows_x86/desktop/qt5_5128/qt.qt5.5128.debug_info.win64_msvc2017_64重点是下载5.12.8-0-202004051457qtbase-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64-debug-symbols.7z和5.12.8-0-202004051457qttools-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64-debug-symbols.7z然后解压到Qt对应的路径。x86 MSVC2017Index of /online/qtsdkrepository/windows_x86/desktop/qt5_5128/qt.qt5.5128.debug_info.win32_msvc2017如果是新版本5.12.9,那就下载5.12.9调试信息(*.pdb文件)Index of /online/qtsdkrepository/windows_x86/desktop/qt5_5129/qt.qt5.5129.debug_info.win64_msvc2017_645.12.9-0-202006121743qtbase-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64-debug-symbols.7z5.12.9-0-202006121743qttools-Windows-Windows_10-MSVC2017-Windows-Windows_10-X86_64-debug-symbols.7z然后解压到Qt对应的路径。如果是新版本5.15.2,那就下载5.15.2调试信息(*.pdb文件)Index of /online/qtsdkrepository/windows_x86/desktop/qt5_5152Index of /online/qtsdkrepository/windows_x86/desktop/qt5_5152/qt.qt5.5152.debug_info.win64_msvc2019_64以上三步实现之后,就可以F11进入源码调试了。(#^.^#)

Windows环境VS2017编译skia库-m84,亲测成功,使用官方编译的方法

环境准备Windows7/10电脑需要能访问https://skia.org/和https://skia.googlesource.com/skia.git在Windows上安装Visual Studio 2017在Windows上安装Python v2.7.x(必须是v2,不能使用v3),32位版本,例如python-2.7.18.msi。环境变量path需要添加python v2.7.x。如果电脑同时还装了v3,那么环境变量path需要把v2排在v3前面。在Windows终端输入命令"python --version"可以查看python2是否正确安装。在Windows上安装Git工具下载源码和依赖库截止目前,skia的版本是m84,https://skia.googlesource.com/skia.git/+refs我们使用Windows终端命令行,把源码下载:1、先设置git http代理:>git config --global http.proxy http://127.0.0.1:8000>git config --global https.proxy http://127.0.0.1:8000设置成功,代理信息会记录在C:\Users\firecat\.gitconfig2、再用git命令下载skia源码>git clone https://skia.googlesource.com/skia.git3、再下载依赖库>cd skia>python tools/git-sync-deps下载gn和ninja工具网上有好心人已经准备好了,直接下载就行了,然后解压到\skia\bin里面。环境变量path需要添加bin路径,例如我的路径是:F:\tmp-source\qt-hmi\skia\skia\bin下载链接:https://download.csdn.net/download/qq_35824650/12398406本人也备份了一份:https://download.csdn.net/download/libaineu2004/12432424源码编译参数说明is_debug=true 表示Debugis_component_build=true 表示动态库编译【推荐,否则是静态库编译,到时候生成的静态库运行时是MTd/MT】target_cpu="x86" 表示Win32平台ide=vs 表示使用VS IDE编译 【不推荐,容易出错】x64位 Debug编译:>bin\gn gen out\Debug64>bin\gn args out\Debug64#这句话输入之后,会弹出一个记事本文件,请手动输入要编译的参数# Set build arguments here. See `gn help buildargs`.is_debug=trueis_component_build=true保存记事本,然后继续终端命令>bin\gn gen out\Debug64>bin\ninja -C out\Debug64x64位 Release编译:>bin\gn gen out\Release64>bin\gn args out\Release64# Set build arguments here. See `gn help buildargs`.is_debug=falseis_component_build=true>bin\gn gen out\Release64>bin\ninja -C out\Release64x86位 Debug编译:>bin\gn gen out\Debug86>bin\gn args out\Debug86# Set build arguments here. See `gn help buildargs`.is_debug=trueis_component_build=truetarget_cpu="x86">bin\gn gen out\Debug86#执行ninja之前,需要先打开路径\skia\out\Debug86的toolchain.ninja文件,手动删除所有"cmd /c C:/Program Files (x86)/Windows Kits/10/bin/SetEnv.cmd /x86 &&"的文本内容,#进入文件夹C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64拷贝以下3个文件到\skia\out\Debug86msobj140.dllmspdb140.dllmspdbcore.dll>bin\ninja -C out\Debug86x86位 Release编译:>bin\gn gen out\Release86>bin\gn args out\Release86# Set build arguments here. See `gn help buildargs`.is_debug=falseis_component_build=truetarget_cpu="x86">bin\gn gen out\Release86#执行ninja之前,需要先打开路径\skia\out\Release86的toolchain.ninja文件,手动删除所有"cmd /c C:/Program Files (x86)/Windows Kits/10/bin/SetEnv.cmd /x86 &&"的文本内容,#进入文件夹C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64拷贝以下3个文件到\skia\out\Release86msobj140.dllmspdb140.dllmspdbcore.dll>bin\ninja -C out\Release86常用的gn命令bin\gn help argsbin\gn help static_librarybin\gn help buildargsbin\gn args --list out\Release64bin\gn args --list out\Debug64bin\gn args --list out\Release86bin\gn args --list out\Debug86bin\ninja -help之前编译失败的命令,也记录一下不建议使用VS的编译方式,容易失败>bin/gn gen out/Static --args="is_official_build=true skia_use_libpng=false skia_use_zlib=false skia_use_libjpeg_turbo=false skia_use_harfbuzz=false skia_use_libwebp=false skia_use_expat=false"vs要用管理员身份打开,不然编译的时候会报错,说什么没有访问权限x64 Debug>bin\gn gen out/vsx64d --ide=vs --args="is_debug=true is_official_build=false is_component_build=true"x64 Release>bin\gn gen out/vsx64 --ide=vs --args="is_debug=false is_official_build=false is_component_build=true"x86 Debug>bin\gn gen out/vsx86d --ide=vs --args="is_debug=true is_official_build=false is_component_build=true target_cpu=\"x86\""x86 Release>bin\gn gen out/vsx86 --ide=vs --args="is_debug=false is_official_build=false is_component_build=true target_cpu=\"x86\""最终编译好的库文件/头文件/案例https://download.csdn.net/download/libaineu2004/12436349参考文献https://www.jianshu.com/p/4225f4342d18 [图形引擎Skia之一]源码下载与编译(Windows)https://blog.drawoceans.com/codes/19/ 在Windows上使用VS2017编译64位和32位Skiahttps://blog.csdn.net/qq_35824650/article/details/105984644 国内正确编译V8和Skiahttps://gitee.com/QtSkia/QtSkia google的 skia渲染框架, 集成到Qt中https://gitee.com/QtSkia/QtSkia/blob/master/doc/Examples-zh.md SkCanvas是一个类似于QPainter的画笔,但性能和功能都比QPainter强大许多。

3.5 线程池基本用法#include <QCoreApplication> #include <QDebug> #include <QRunnable> #include <QThread> #include <QThreadPool> class MyRun : public QRunnable public: MyRun() ~MyRun() public: void run() int i = 3; while (i) qDebug() << "thread start:" << QThread::currentThreadId(); QThread::msleep(500); int main(int argc, char *argv[]) QCoreApplication a(argc, argv); qDebug() << "Main:" << QThread::currentThreadId(); QThreadPool m; m.setMaxThreadCount(2); m.setExpiryTimeout(-1); MyRun *run = new MyRun; if (!run->autoDelete()) qDebug() << "QRunnable's autoDelete default value is not true"; run->setAutoDelete(true); qDebug() << m.maxThreadCount() << m.expiryTimeout(); qDebug() << m.activeThreadCount(); m.start(run); qDebug() << m.activeThreadCount(); m.waitForDone(); qDebug() << m.activeThreadCount(); return 0; }3.6 线程池内的子线程发信号需要派生QObject!class MyThread_draw2D_SectionChart : public QObject, public QRunnable Q_OBJECT public: MyThread_draw2D_SectionChart(int frameNo) : m_iFrameNo(frameNo) virtual ~MyThread_draw2D_SectionChart() qDebug() << "~MyThread"; public: virtual void run(); private: int m_iFrameNo; signals: void sig_updateUI_SectionChart(int frameNo); };4、子线程发信号给主线程,更新UI通过信号槽的机制可以实现,子线程发信号给主线程即可。不会阻塞。启动线程m_future_2d_SectionChart = QtConcurrent::run(this, &FormContent::thread_draw2D_SectionChart);子线程void FormContent::thread_draw2D_SectionChart(void)//绘制2D截面图{ qDebug() << "sub thread id:" << QThread::currentThreadId(); connect(this, SIGNAL(sig_updateUI_SectionChart()), this, SLOT(slot_updateUI_SectionChart()));while (true){//去主线程更新UI  emit sig_updateUI_SectionChart();}}主线程void FormContent::slot_updateUI_SectionChart(void)//更新2D截面图{   qDebug() << "main thread id:" << QThread::currentThreadId(); m_pFormTimeline->updateSectionChart();}5、数据保护,加锁解锁QMutex 提供相互排斥的锁,或互斥量;有递归和非递归之分;QMutexLocker 是一个辅助类,自动对 QMutex 加锁与解锁;QReadWriterLock 提供了一个可以同时读操作的锁;有递归和非递归之分;QReadLocker与QWriteLocker 自动对QReadWriteLock 加锁与解锁;QSemaphore 提供了一个整型信号量,是互斥量的泛化;QWaitCondition 提供了一种方法,使得线程可以在被另外线程唤醒之前一直休眠。https://doc.qt.io/qt-5/qmutex.htmlhttps://doc.qt.io/qt-5/qmutexlocker.htmlhttps://doc.qt.io/qt-5/qreadlocker.htmlhttps://doc.qt.io/qt-5/qwritelocker.htmlhttps://doc.qt.io/qt-5/qreadwritelock.htmlhttps://doc.qt.io/qt-5/qsemaphore.htmlhttps://blog.csdn.net/guoyufeng25/article/details/1031052446、线程优先级Qthread的优先级属性:Priority指示系统如何调度线程。QThread::IdlePriority 0scheduled only when no other threads are running.QThread::LowestPriority 1scheduled less often than LowPriority.QThread::LowPriority 2scheduled less often than NormalPriority.QThread::NormalPriority 3the default priority of the operating system.QThread::HighPriority 4scheduled more often than NormalPriority.QThread::HighestPriority 5scheduled more often than HighPriority.QThread::TimeCriticalPriority 6scheduled as often as possible.QThread::InheritPriority 7use the same priority as the creating thread. This is the default.x、多线程的高级应用TCP Client/TCP Serverhttps://sourceforge.net/projects/threader-qt/https://sourceforge.net/p/threader-qt/svn/HEAD/tree/future/promise【推荐】https://github.com/mhogomchungu/tasksy、参考文献https://github.com/czyt1988/czyBlog/tree/master/tech/QtThreadhttps://www.cnblogs.com/xia-weiwen/p/10306089.htmlhttps://github.com/Xia-Weiwen/CopyFile

Qt5多线程/线程池技术集锦(1)

1、用QObject的方法实现多线程Qt有两种多线程的方法,其中一种是继承QThread的run函数,另外一种是把一个继承于QObject的类转移到一个Thread里。 Qt4.8之前都是使用继承QThread的run这种方法,但是Qt4.8之后,Qt官方建议使用第二种方法。第二种方法用QObject来实现多线程有个非常好的优点,就是默认就支持事件循环(Qt的许多非GUI类也需要事件循环支持,如QTimer、QTcpSocket),QThread要支持事件循环需要在QThread::run()中调用QThread::exec()来提供对消息循环的支持,否则那些需要事件循环支持的类都不能正常发送信号,因此如果要使用信号和槽,那就直接使用QObject来实现多线程。https://doc.qt.io/qt-5/threads.htmlhttps://wiki.qt.io/QThreads_general_usagehttps://wiki.qt.io/Threads_Events_QObjects2、用QtConcurrent::run的方法实现多线程https://doc.qt.io/qt-5/qtconcurrentrun.htmlhttps://www.coologic.cn/2017/12/608/2.1 基本的使用方式,注意线程id的获取方式是QThread::currentThreadId();QString id = QString::asprintf("[%d]", QThread::currentThreadId());#include <QCoreApplication> #include <QDebug> #include <QList> #include <QThread> #include <QtConcurrent> void function(const QList<int> &param1, const int &param2, Qt::HANDLE main_id) qDebug() << "function param:" << param1 << param2 << main_id; qDebug() << "function thread id:" << QThread::currentThreadId(); int main(int argc, char *argv[]) QCoreApplication a(argc, argv); QList<int> testVactor; for (int i = 1; i <= 3; i++) testVactor.push_back(i); qDebug() << "main thread id:" << QThread::currentThreadId(); QFuture<void> f = QtConcurrent::run(function, testVactor, 666, QThread::currentThreadId()); f.waitForFinished(); //要等待,否则线程没运行完程序结束会出错 return 0; }2.2 指定线程池的使用方式有时候希望运行的函数在全局线程池或者局部线程池运行,而不是有qt托管处理,可以进行如下方式调用:extern void aFunction();QThreadPool pool;QFuture<void> future = QtConcurrent::run(&pool, aFunction);QtConcurrent::run和线程池组合使用的源码案例:#include <QCoreApplication> // Qt includes #include <QtConcurrent> #include <QtCore> #include <QtGui> #include <QtNetwork> #if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0)) #include <QtWidgets> #endif QThreadPool m_threadpool; void func(void) qDebug() << "hello"; QFuture<void> f4 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 1000; i < 1010; i++) qDebug() << i; Sleep(1000); int main(int argc, char *argv[]) QCoreApplication a(argc, argv); //初始化线程池 int cpu = std::thread::hardware_concurrency(); qDebug() << "cpu:" << cpu; m_threadpool.setMaxThreadCount(cpu); m_threadpool.setExpiryTimeout(-1); QFuture<void> f1 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 0; i < 10; i++) qDebug() << i; Sleep(1000); QFuture<void> f2 = QtConcurrent::run(&m_threadpool, [&](void) { for (int i = 100; i < 110; i++) qDebug() << i; Sleep(1000); QFuture<void> f3 = QtConcurrent::run(func); while (true) return a.exec(); 2.3 使用QFutureWatcher实现进度条的例子https://wiki.qt.io/Progress_Bar\Qt5.12.9\Examples\Qt-5.12.9\qtconcurrent\progressdialog长时间进行操作时,通常需要显示进度条。 在某些耗时的运算中,我们没有方法来实时跟踪操作的进度,所知的只是运算完成时。 为了实现进度条,您可以使用progressBar小部件,然后在另一个线程中运行该操作(使用moveToThread)。 这通常需要创建一个特殊的对象(QObject的子类,该对象运行操作,然后发出finish信号),如果您需要对许多不同的操作执行此操作,则可能会很麻烦。但是,使用QFutureWatcher和QtConcurrent::run(),这非常容易。 这篇官方文档演示如何将这种技术与QProgressDialog和QProgressBar一起使用。如果QProgressBar最小值和最大值都设置为0,进度条会显示一个繁忙指示,而不会显示当前的值。3、线程池3.1 全局线程池QThreadPool提供了一个静态成员函数,QThreadPool *  globalInstance(),使用此方法可获取一个当前进程的全局线程池,可在多个类中共同使用一个线程池。3.2 局部线程池和常规类的使用相同,可以通过QThreadPool pool;类的实例化方式建立一个局部线程池,并由当前类维护,可保证此线程池仅供当前类应用。3.3 QThreadPool启动的线程,需要从QRunnable类继承。需要实现QRunnable类的run虚函数。QRunnable的autoDelete默认返回true,若需要更改需要调用setAutoDelete进行更改。QRunnable只有run、autodelete、setautodelete这三个关键函数。3.4 主要的几个函数int activeThreadCount() const //当前的活动线程数量void clear()//清除所有当前排队但未开始运行的任务int expiryTimeout() const//线程长时间未使用将会自动退出节约资源,此函数返回等待时间。默认值30000ms。int maxThreadCount() const//线程池可维护的最大线程数量。默认值CPU核心数*2。void setExpiryTimeout(int expiryTimeout)//设置线程回收的等待时间;可以设置为-1,没有超时限制。void setMaxThreadCount(int maxThreadCount)//设置最大线程数量void start(QRunnable *runnable, int priority = 0)//加入一个运算到队列,注意start不一定立刻启动,只是插入到队列,排到了才会开始运行。需要传入QRunnable,priority是线程优先级。 bool waitForDone(int msecs = -1)//等待所有线程运行结束并退出,参数为等待时间,-1表示一直等待到最后一个线程退出https://doc.qt.io/qt-5/qthreadpool.htmlhttps://doc.qt.io/qt-5/qrunnable.htmlhttps://www.cnblogs.com/techiel/p/8018379.html

"\Tools\QtCreator\bin\clangbackend.exe" could not be started

Windows环境,每次打开Qt Creator都会报错:2020-05-10T09:54:37 Clang Code Model: Error: The clangbackend executable "F:\Qt\Qt5.12.8\Tools\QtCreator\bin\clangbackend.exe" could not be started (timeout after 10000ms).解决方法如下:Qt Creator->菜单->帮助->关于插件->C++->去掉ClangCodeModel->重启Qt Creator

Windows环境VS2017编译skia库,亲测成功,借助skui的方法

Skia简介Skia是一个开源的二维图形库,提供各种常用的API,并可在多种软硬件平台上运行。谷歌Chrome浏览器、Chrome OS、Fuchsia、安卓、Flutter、火狐浏览器、火狐操作系统以及其它许多产品都使用它作为图形引擎。Skia由谷歌出资管理,任何人都可基于BSD免费软件许可证使用Skia。Skia开发团队致力于开发其核心部分, 并广泛采纳各方对于Skia的开源贡献。源代码: skia.googlesource.com/skia提议: bug.skia.org论坛: skia-discuss@googlegroups.comskia官网: https://skia.org谷歌github镜像: https://github.com/google/skiaSkui简介本人亲测,采用Google官方提供的编译方式很难成功。偶然发现了skui这个开源项目。skui使用了skia库。Skia-based C++ UI frameworkhttps://github.com/skui-org/skuihttps://blog.csdn.net/czhzasui/article/details/103457105因为编译skui的过程,会编译skia库,殊途同归,最终可以得到我想要的skia库。Skui编译下面描述编译过程:1、我的编译环境:Win7 x64,VS20172、源码下载,注意Windows和Linux命令行的\和/的区别。从github上克隆仓库git clone https://github.com/skui-org/skui.git进入仓库cd skui更新子模块仓库git submodule update --init --recursive如果网络不好,可能会在拉取skia的时候卡住,这时候进入3rdparty目录再次拉取cd 3rdpartygit submodule update --init --recursivecd ..这样就拉取了skui所有源码。如果实在还是拉取不成,那就直接点击github相关的链接,进入后,手动下载。点击进入“3rdparty”目录,进入页面,使用页面默认的版本,下载skia源码3、源码准备好,就可以编译mkdir ..\skui-buildcd ..\skui-build接下来,可以选择MSVC编译,也可以选择Ninja编译cmake ..\skui -G "Visual Studio 15 2017 Win64"或者 cmake ..\skui -G Ninjacmake --build .笔者注:如果是使用MSVC编译,个人建议还是使用cmake-gui.exe可视化的方式代替命令行。MSVC编译,请选择Windows SDK v10.x版本,千万不要选v8.1版本,否则编译skia库会失败。另外,cmake工程选项,使用默认值,不做任何修改。skia是静态库编译,MDd/MD的运行时库。4、运行一下例程,是个很小的弹出窗口。F:\tmp-source\qt-hmi\skia\skui-build>examples\widget_gallery\debug\widget_gallery.exe5、关于widget_gallery.exe运行报异常的问题,我提交了issueshttps://github.com/skui-org/skui/issues/12If you want to play around with the code as is, you can change gui/window_windows.c++:L29 to this:const window_flags window::default_flags = window_flag::exit_on_close | window_flag::anti_alias;---https://ninja-build.org/https://github.com/ninja-build/ninjahttps://blog.csdn.net/qq_20373723/article/details/84061647 windows 安装ninja

开源项目推荐:SCADA组态软件Qt,kanzi,C#,MFC和WEB大全(收藏版)

尊重作者,支持原创,如需转载,请附上原地址:https://blog.csdn.net/libaineu2004/article/details/797157371、PC端之QtHmiFuncDesignerhttps://github.com/VelsonWang/HmiFuncDesigner 高仿武汉舜通QTouch,请重点关注libaineu2004/HmiFuncDesigner 国内镜像读开源QScada框架HmiFuncDesigner-master的笔记https://github.com/VelsonWang/designer 项目源码来自Qt Designer源码https://github.com/VelsonWang/AppDemo 项目源码修改自Qt Creator源码,保留了基本的插件框架LVGLBuilderGUI Builder for littlevgl 仿自Qt设计师https://github.com/CURTLab/LVGLBuilderhttps://github.com/mrQzs/Lvgl_Simulatorhttps://github.com/mrQzs/CreateLvglLibQt Design StudioQt Design Studio是一款UI设计和开发工具,它让设计师和开发者可以迅速设计原型,并且开发复杂的可伸缩的UI。简单概括其功能就是让UI设计转换为qml,为工程师所用。Qt Design Studio源码源自qt creator的分支。Qt Design Studio简介及源码下载_$firecat全宏的代码足迹$-CSDN博客Device_Studiohttps://github.com/ybjx1987/Device_Studio 前同事写的组态软件基础框架pvbrowserpvbrowser – The Process Visualization Browser. HMI and Scada for every platform.https://github.com/pvbrowser/pvbOtherhttps://github.com/ShellAlbert/LaserHMIhttps://github.com/IndeemaSoftware/QSimpleScada 简易版组态软件https://github.com/michpolicht/CuteHMI2、PC端之kanzikanzi目前主要聚焦在车载领域,cluster、IVI、HUD等,3D引擎是其主要特点。Rightware已经隶属于中科创达。Qt出现的更早,应用也更加广泛。但是就车载领域而言,kanzi开发效率更高。Kanzi 2.8.2 is released!3、PC端之C#RapidScadaRapid SCADA | Free, Open Source, Full Featured SCADA Softwarehttps://github.com/RapidScadaSharpSCADAhttps://github.com/qwe7922142/SharpSCADALitehttps://github.com/GavinYellow/SharpSCADAOtherhttps://github.com/AlexDovgan/FreeSCADA老坏猫 - 博客园4、PC端之VC++/MFChttps://github.com/gitZaiZai/YsbotControlhttps://github.com/qinyong99/SuperCxHMI最完整的工业组态软源代码_web组态框架,wpf工业组态控件-专业指导文档类资源-CSDN下载组态王源代码_组态王代码-项目管理代码类资源-CSDN下载freescada开源wpf组态软件_freescada,开源组态软件-互联网代码类资源-CSDN下载http://www.genlogic.com/5、PC端之Javahttps://github.com/SCADA-LTS/Scada-LTS 尊重作者,支持原创,如需转载,请附上原地址:https://blog.csdn.net/libaineu2004/article/details/797157376、Web端智物联工业物联网底层系统:网页版组态软件参考网站,可供物联网行业应用参考FIDIS(全称Flexible information data integrate system,柔性信息与数据集成系统),作为智物联工业物联网体系中的应用系统平台,承担着MixIOT应用数据的展示,以及与MixIOT系统的操作和交互。同时,FIDIS系统作为底层应用平台,支持基于OpenFrame开发框架的应用的二次开发。https://github.com/mixlinker/fidisMixlinker知识体系PyScada is a open source scada system that uses the Django framework as backendhttps://github.com/trombastic/PyScadale5le-topology是一款开源、易扩展、方便集成的在线绘图(微服务架构图、网络拓扑图、流程图、活动图、时序图、类图、思维导图/脑图、动画等)的软件项目。乐吾乐Topology - 基于开源的免费可视化绘图工具topology一个轻量(100k左右)、功能丰富的绘图工具(微服务架构图、拓扑图、流程图、类图等ULM图、脑图,动画、视频支持)https://github.com/le5le-com/topologyOSHMI OSHMI是一种基于现代开源HTML5的HMI,它是为变电站自动化而从头开始构思的,但它可以用于任何其他自动化领域,如工业生产、楼宇系统、物联网等。OSHMI Open Substation HMIOSHMI - Open Substation HMI download | SourceForge.nethttp://ksylvest.github.io/jquery-gridly/http://www.lanrenzhijia.com/demos/40/4004/demo/http://jgraph.github.io/mxgraph/javascript/examples/grapheditor/www/index.htmlhttp://jgraph.github.io/mxgraph/javascript/https://github.com/riclolsen/OSHMI  OSHMI是一种基于现代开源HTML5的HMI,它是为变电站自动化而从头开始构思的,但它可以用于任何其他自动化领域,如工业生产、楼宇系统、物联网等。https://github.com/UsrIot 有人物联网IntegraXor Web SCADA – Ecava IGX SCADA ECAVA INTEGRAXOR WEB SCADAtopology.le5le乐吾乐Topology - 基于开源的免费可视化绘图工具https://github.com/le5le-com/topologyFUXAWeb-based Process Visualization (SCADA/HMI/Dashboard) softwarehttps://github.com/frangoteam/fuxa/7、一个流行的设备采集,程序通讯,跨平台的组件框架首页 - HslCommunication 官网https://github.com/dathlinHslCommunication组件库使用说明 - dathlin - 博客园8、dugigeek本软件是融合其他多种行业软件特性而开发的针对SCADA、HMI、FSU,DTU, 等物联网设备网的综合定制和开发软件平台,软件目标是提供包括硬件选型、固件研发、应用软件,产品测试等”壹套龙服务“,软件源码将采取保姆模式永久开源!http://www.dugigeek.com/https://gitee.com/dugiware/dugitoolshttps://gitee.com/dugiiot/dugiiotcadx、其他组态软件(1)厦门海为 haiwell厦门海为科技有限公司【官网】-工业物联网|国产PLC|HMI|SCADA(2)武汉舜通 QTouchQTouch跨平台软件_通讯管理机_电力监控_能源管理系统 — 武汉舜通智能(3)ucancodehttp://www.ucancode.com/  付费软件,中文http://www.uccpsoft.com/index.htmhttp://www.ucancode.net/ 英文下面是Linux下VX++源码的评估版本下载地址和信息:http://www.uccpsoft.com/HMI_SCADA_LINUX_QT.htmhttp://www.uccpsoft.com/download/VXEval2021.ziphttp://www.uccpsoft.com/download/EFOEval2021Full.zip(4)LVGL - Light and VersatileGraphics LibraryLVGL是一个开源图形库,提供您创建嵌入式GUI所需的一切,易于使用的图形元素,美丽的视觉效果和低内存占用。LVGL - Light and Versatile Embedded Graphics Libraryhttps://github.com/lvgl/lvglqt_lvgl: littlevgl的PC端QT平台仿真Running LittlevGL PC Simulator from Qt-Creator in Windows | LVGL’s Blog ++ https://github.com/ScarsFun/pc_simulatorQt 编译 littlevGL_Eric-CSDN博客 Qt 编译 littlevGL基于QT的LVGL 7.0 DEMO演示工程 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 基于QT的LVGL 7.0 DEMO演示工程GUI Guider是恩智浦为LVGL开发了一个上位机GUI设计工具,可以通过拖放控件的方式设计LVGL GUI页面,加速GUI的设计。设计完成的GUI页面可以在PC上仿真运行,确认设计完毕之后可以生成C代码,再整合到MCU项目中。进入NXP官网恩智浦半导体官方网站 | 主页,的软件中心搜索:GUI Guider,即可找到。GUI Guider | NXP SemiconductorsGUI Guider_NXP 半导体(5)AWTKAWTK 全称为 Toolkit AnyWhere,是 ZLG倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎,并支持跨平台同步开发https://github.com/zlgopen/awtkawtk: AWTK 全称为 Toolkit AnyWhere,是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎,并支持跨平台同步开发其中AWTK Designer是界面设计工具。---尊重作者,支持原创,如需转载,请附上原地址:https://blog.csdn.net/libaineu2004/article/details/79715737

开源项目推荐:OpenGL之gult/freeglut/glew/glfw/glad的联系与区别

本篇内容主要参考了文章:https://blog.csdn.net/AvatarForTest/article/details/79199807,但是经过本人局部修改,并添加了个人见解。1.OpenGL总览OpenGL只有框架没有实现,换句话说就是OpenGL只有函数声明没有源文件实现,类似于接口和虚函数。所有的实现是显卡生产商提供。比如NVIDIA或者AMD就要自己实现OpenGL函数内容,所以不同的生产商可以对自己的产品提供优化,毕竟代码是自己写的。OpenGL函数库相关的API有核心库(gl),实用库(glu),辅助库(aux)、实用工具库(glut),窗口库(glx、agl、wgl)和扩展函数库等。gl是核心,glu是对gl的部分封装。glx、agl、wgl 是针对不同窗口系统的函数。glut是为跨平台的OpenGL程序的工具包,比aux功能强大(aux很大程度上已经被glut库取代)。扩展函数库是硬件厂商为实现硬件更新利用OpenGL的扩展机制开发的函数。https://opengl.org/2.gultOpenGL Utility Toolkithttps://www.opengl.org/resources/libraries/glut/glut_downloads.php里面有32位的库文件下载,glutdlls37beta.zip,但是版本太老了,理应被时代淘汰,不推荐使用。gult最后版本v3.7beta的历史可追溯至1998年8月,且该项目已经被废弃。它的许可证禁止任何人发布修改后的库代码。这部分函数以glut开头,主要包括窗口操作函数,窗口初始化、窗口大小、窗口位置等函数;回调函数:响应刷新消息、键盘消息、鼠标消息、定时器函数等;创建复杂的三维物体;菜单函数;程序运行函数。gult对应的开源实现是freegult。3.freeglutFreeGLUT is a free-software/open-source alternative to the OpenGL Utility Toolkit (GLUT) library因为OpenGL没有窗口管理的功能,所以很多热心的人写了工具来支持这些功能,比如早期的glut,现在的freeglut等。freeglut完全兼容glut,是glut的代替品,开源,功能齐全。目前来看,freeglut 3.0版本比其它版本稳定,推荐使用。帕维尔在1999年12月1日开始freeglut的开发。目前,该项目几乎可以100%的替代原来的GLUT,只有少数差别(如,the abandonment of SGI-specific features,按钮盒子和动态视频分辨率)和 其他一小部分程序Bug。http://freeglut.sourceforge.net/4.glewThe OpenGL Extension Wrangler Libraryglut或者freegult主要是OpenGL 1.0的基本函数功能;glew是使用OpenGL 2.0之后的一个工具函数。不同的显卡公司,也会发布一些只有自家显卡才支持的扩展函数,你要想用这数涵数,不得不去寻找最新的glext.h,有了GLEW扩展库,你就再也不用为找不到函数的接口而烦恼,因为GLEW能自动识别你的平台所支持的全部OpenGL高级扩展函数。也就是说,只要包含一个glew.h头文件,你就能使用gl,glu,glext,wgl,glx的全部函数。glew包含了OpenGL所需的核心。前面已经说过openGL的实现是显卡生产商,那么系统如何才能找到这些实现好的函数呢?而且不同的平台函数存放地方还不同,文件结构也不同。有没有一种方式能够自动找到OpenGL的函数?这就是glew的作用:用来找openGL的函数,并初始化,这样我们就能直接调用OpenGL的函数了。http://glew.sourceforge.net/5.glfwglfw is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan development on the desktop. It provides a simple API for creating windows, contexts and surfaces, receiving input and events.glfw无愧于其号称的lightweight的OpenGL框架,的确是除了跨平台必要做的事情都没有做,所以一个头文件,很少量的API,就完成了任务。glfw的开发目的是用于替代glut的。它是一个轻量级的,开源的,跨平台的library。支持OpenGL及OpenGL ES,用来管理窗口,读取输入,处理事件等。那么glfw有何优势呢?glut太老了,最后一个版本还是90年代的。freeglut完全兼容glut,算是glut的代替品,功能齐全,但是bug太多。稳定性也不好(不是我说的啊),glfw应运而生。总之,glfw是glut/freegult的升级和改进。glfw是用来显示窗口和捕捉窗口事件的一套API,可以理解成Qt和windows平台的WPF。OpenGL只是一套控制GPU的规则,并没有对于跨平台窗口显示和事件进行规定,所以需要一个显示显卡渲染的窗口,这就是glfw的作用。https://www.glfw.org/6.gladMulti-Language GL/GLES/EGL/GLX/WGL Loader-Generatorglad是继gl3w,glew之后,当前最新的用来访问OpenGL规范接口的第三方库。简单说glad是glew的升级版,就是说glew比较老,glad比较新。https://glad.dav1d.de/7.结论与项目使用窗口管理老产品:glut/freeglut替代品:glfw函数加载老产品:glew替代品:glad项目开发,通常有三种组合(1)freeglut+glew(2)glfw+glew(3)glfw+glad其中组合1是经典,组合3比较新潮。测试#include <Windows.h> #include <stdio.h> #include <GL/glut.h> int main(int argc, char** argv) glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(300, 300); glutInitWindowPosition(100, 100); glutCreateWindow("OpenGL Version"); const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字 const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬件平台 const GLubyte* OpenGLVersion = glGetString(GL_VERSION); //返回当前OpenGL实现的版本号 const GLubyte* gluVersion = gluGetString(GLU_VERSION); //返回当前GLU工具库版本 printf("OpenGL实现厂商的名字:%s\n", name); printf("渲染器标识符:%s\n", biaoshifu); printf("OpenGL实现的版本号:%s\n", OpenGLVersion); printf("OGLU工具库版本:%s\n", gluVersion); //如果是在VS上执行,需要在return前加上:system("pause"); return 0; }x1.源码和库下载https://download.csdn.net/download/libaineu2004/12402662更多的详情请访问我的另一篇博文:https://libaineu2004.blog.csdn.net/article/details/105308235x2.参考文献学习教程https://learnopengl-cn.github.io/ ++ https://learnopengl.com/https://github.com/JoeyDeVries/LearnOpenGL ++ https://github.com/JoeyDeVries/Cellhttp://www.opengl-tutorial.org/ ++ https://github.com/opengl-tutorials/oglOpenGL超级宝典visual studio 2013开发环境配置 GLToolshttp://www.it165.net/pro/html/201504/38164.htmlOpenGL+VS2017 环境配置(亲测好使)https://blog.csdn.net/AvatarForTest/article/details/79199807《OpenGL编程指南》红宝书,Khronos小组编写的OpenGL官方权威指南《OpenGL超级宝典》蓝宝书,配套源码使用的是freeglut+glewOpenGL GUINanoGUI 是基于opengl以及GLFW,GLAD,NanoVG,Eigen这些库形成的一个可视化GUI库,在窗口的设计上非常的简约,程序使用上也非常的方便。https://github.com/wjakob/nanoguihttps://github.com/memononen/NanoVGhttps://nanogui.readthedocs.io/en/latest/libqglviewerlibQGLViewer 是一个用以简化了Qt开发OpenGL三维浏览器的C++库。它提供了一些典型的3D查看器的功能,如能够移动相机使用鼠标。http://libqglviewer.com/https://github.com/GillesDebunne/libQGLViewer

Qt自定义控件之颜色对话框QColorDialog/Qt Color Widgets

1、官方自带Qt官方自带的QColorDialog类提供了一个指定颜色的对话框部件。#include <QColorDialog>QColor i = QColorDialog::getColor(Qt::red, this,                                          tr("颜色对话框"),                                          QColorDialog::ShowAlphaChannel);2、自定义但是好多开源项目都使用了自定义控件Qt Color Widgets。https://gitlab.com/mattia.basaglia/Qt-Color-WidgetsC++使用方法:1.pro文件LIBS += -L$${DESTDIR} #lib pathLIBS += "QtColorWidgets-Qt52.lib"INCLUDEPATH += ../color_widgets/include/INCLUDEPATH += ../color_widgets/include/QtColorWidgets/2.cpp源文件#include "color_dialog.hpp" void Designer::on_actionColor_triggered() color_widgets::ColorDialog dlg; connect(&dlg, &color_widgets::ColorDialog::colorSelected, this, &Designer::color_changed); dlg.exec(); void Designer::color_changed(QColor color) int r, g, b, a; color.getRgb(&r, &g, &b, &a); color.getHsv(&r, &g, &b, &a); }https://github.com/pencil2d/pencilhttps://github.com/douzhongqiang/EasyCanvashttps://github.com/caryoscelus/rainynite-studiohttps://github.com/caryoscelus/Qt-Color-Widgets------https://github.com/frankosterfeld/qtkeychain独立于平台的Qt API,用于安全存储密码。

好工具推荐系列:跨平台安卓实时投屏软件QtScrcpy

Android实时投屏软件,此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限。软件是开源的,C++/Qt:https://gitee.com/Barryda/QtScrcpyhttps://github.com/barry-ran/QtScrcpy运行在你的电脑上接入Android设备,然后运行程序,按顺序点击如下按钮即可连接到Android设备无线连接步骤(保证手机和电脑在同一个局域网):安卓手机端在开发者选项中打开usb调试通过usb连接安卓手机到电脑点击刷新设备,会看到有设备号更新出来点击获取设备IP点击启动adbd无线连接再次点击刷新设备,发现多出了一个IP地址开头的设备,选择这个设备启动服务备注:启动adbd以后不用再连着usb线了,以后连接断开都不再需要,除非安卓adbd停了需要重新启动-----------------------原作者的博客https://blog.csdn.net/rankun1/article/details/87970523QtScrcpy软件的原型https://github.com/Genymobile/scrcpy

Qt Design Studio简介及源码下载

1、简介Qt Design Studio是一款UI设计和开发工具,它让设计师和开发者可以迅速设计原型,并且开发复杂的可伸缩的UI。简单概括其功能就是让UI设计转换为qml,为工程师所用。Qt Design Studio的详细特性:QtPhotoshop Bridge —— 在Photoshop中创建您的UI设计和UI组件,然后把它们导入到Qt Design Studio中。这包含一个先进的Photoshop插件,它能把您的设计翻译成QML语言,并导入到Qt Design Studio中。基于时间轴的动画 —— 创建高级动画从来都不是容易的事情。基于时间轴/关键帧的编辑器,它能让设计师为各种类型元素创造每个像素都完美的动画,而不需要写任何一行代码。QMLLive Preview —— 在桌面、Android设备、Boot2Qt设备上直接运行和预览您的应用。实时地在目标设备上检查您修改的效果。QMLVisual Effects  —— 在您的设计上直接应用开箱即用的可视效果。例如:模糊、上色、发光或更多。您甚至可以在时间轴编辑器中添加可视效果动画。QMLShape Items —— 许多个开箱即用的形状,例如:扇形,弧线、三角形等,随时可以帮助设计原型和创建定制的QML可视效果。管理和创建定制的、可复用的元件 —— 只需几次鼠标点击一可以把Photoshop的图层变成可以被不同项目复用的元件。2、官网https://www.qt.io/designhttps://www.qt.io/cn/ui-frameworkhttps://wiki.qt.io/QtDesignStudiohttps://doc.qt.io/qtdesignstudio/index.htmlhttps://download.qt.io/official_releases/qtdesignstudio/3、如何获得源码Qt Design Studio源码是开放的,并且源自qt creator的分支。我于2020/04/17曾经发邮件给Qt官方,得到的答复是:问:Is qtdesignstudio open source? Where can I download the source code?答:Yes, it is under GPLv3 license. Sources are located in the qds-1.59 branch of Qt Creator https://code.qt.io/cgit/qt-creator/qt-creator.git/?h=qds-1.594、源码分支下载https://github.com/qt-creator/qt-creator/tree/qds-1.59https://github.com/qt-creator/qt-creator/tree/qds/v1.5.0https://github.com/qt-creator/qt-creator/tree/qds/v1.6.1https://github.com/qt-creator/qt-creator/tree/qds/v2.0.0

Python开源游戏推荐,《帝国时代2》

声明:项目非本人原创,仅仅分享链接!openage:一个志愿者项目,用于创建《帝国时代》,《帝国时代II》(HD)和《星球大战:银河战场》所使用的Genie引擎的免费引擎克隆,与OpenMW,OpenRA,OpenSAGE,OpenTTD和OpenRCT2等项目相当。 目前,我们主要致力于帝国时代II的集成,同时主要针对POSIX平台,例如GNU / Linux。开放性使用原始游戏资产(例如声音和图形),但是(出于明显的原因)不发行它们。 要播放,您需要安装原始的AoE II:TC或AoE II:HD(通过Wine或Steam-Linux)。https://github.com/SFTtech/openage/openage - free, modern RTS game engine

类似Qt之GUI,但比Qt小的多 -- 适用于嵌入式/SoC/单片机/MCU等的界面库

GUI框架GOSP提供类似Qt的API接口,仅需要几百KB的硬件资源(比Qt小的多),能运行在Qt不支持的低性能领域(对Qt形成补充)https://gitee.com/giveda/GOSPGuiLite大道至简 -- 5千行,仅头文件,全平台 GUI库https://github.com/idea4good/GuiLite/https://gitee.com/idea4good/GuiLiteAWTK = Toolkit AnyWhere(为嵌入式、手机和PC打造的通用GUI系统)AWTK 全称为 Toolkit AnyWhere,是 ZLG(周立功) 倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎,并支持跨平台同步开发https://github.com/zlgopen/awtkhttps://gitee.com/zlgopen/awtkIMGUIhttps://github.com/ocornut/imguihttps://github.com/aiekick/ImGuiFontStudiohttps://github.com/aiekick/ImGuiFileDialog其他https://github.com/cnjinhao/nanahttps://github.com/MyGUI/myguihttps://github.com/Dovyski/cvui A (very) simple UI lib built on top of OpenCVhttps://github.com/wjakob/nanogui Minimalistic GUI library for OpenGL类似Qt的信号槽但不需要moc;基于c++11,用于解耦合https://gitee.com/giveda/gobject_cpp11官网GOSP = Giveda® Open Source Projecthttp://giveda.com/

Qt Marketplace -- 强大丰富的Qt市场

Qt Marketplace是一个类似微软VS Marketplace的社区网站。https://marketplace.qt.io/https://marketplace.visualstudio.com/Qt Marketplace(即:Qt 市场)是 Qt 社区推出的一个创新平台,它是Qt有用扩展的全面集合,为开发人员和设计人员提供了大量的 Qt 扩展,以增强 Qt 设计和开发的工作流程;并且它还为合作伙伴提供了一个独特而广泛的渠道,以推广和销售 Qt 扩展和应用程序。Qt Marketplace为开发人员提供了Qt框架库,Qt Creator插件和各种工具,从而提高了开发效率。对于Qt社区来说,启动市场是一个非常大的里程碑和成就,在开发过程中与Qt合作,并着手扩展到市场,目前在Qt 市场上已经有一百多个扩展。以下是一些非常有用的扩展介绍:Felgo:使开发人员可以使用200多个其他Qt APIS和独特的Qt工具(用于台式机,嵌入式和Web)缩短开发时间并提高效率。CTK:生物医学图像计算工具包,当前工作的主要范围是 DICOM、DICOM Application Hosting、Widgets、Plugin Framework。Incredibuild:Qt Creator 用户可以利用网络中可用机器的 CPU 能力,极大地加快构建时间(快 10 倍)。KDAB KUESA:为设计人员和开发人员提供了集成的统一工作流,以在3D或2D / 3D软件用户界面中创建,优化和集成3D。…Qt Marketplace 还允许个人或者公司在全球过百万开发者的 Qt 生态系统中上传、推广和出售其免费和商业的扩展。也就是说,如果你有任何优秀的 Qt 扩展,都可以提交至 Qt Marketplace,不但能成为 Qt 的合作伙伴,还能够向所有人开放自己的作品,从而开拓新的收入来源并扩展客户群。目前,对于付费内容,只有增值税注册公司才能发布付费内容,计划在明年年底之前会开放对个人弃用付费内容。Qt Marketplace支持一次性和定期付款模式。---------------------------------更多的资讯请访问官网https://www.qt.io/cn/blog/qt-marketplacehttps://www.qt.io/blog/qt-marketplacehttps://marketplace.qt.io/https://www.qt.io/market-place-extension-qt

Qt在pro中设置运行时库MT、MTd、MD、MDd

Qt在pro中设置运行时库MT、MTd、MD、MDd,重点关注QMAKE_CFLAGS多线程调试Dll (/MDd) 对应的是MD_DynamicDebug多线程Dll (/MD) 对应的是MD_DynamicRelease多线程(/MT) 对应的是MD_StaticRelease多线程(/MTd)对应的是MD_StaticDebugwin32:CONFIG(debug, debug|release): { LIBS += -L$$QMAKE_SKIA_DIR/out/Debug-x64 INCLUDEPATH += $$QMAKE_SKIA_DIR/out/Debug-x64 DEPENDPATH += $$QMAKE_SKIA_DIR/out/Debug-x64 QMAKE_CFLAGS_DEBUG += -MTd QMAKE_CXXFLAGS_DEBUG += -MTd else:win32:CONFIG(release, debug|release): { LIBS += -L$$QMAKE_SKIA_DIR/out/Release-x64 INCLUDEPATH += $$QMAKE_SKIA_DIR/out/Release-x64 DEPENDPATH += $$QMAKE_SKIA_DIR/out/Release-x64 #win32:QMAKE_CXXFLAGS += /MD QMAKE_CFLAGS_RELEASE += -MT QMAKE_CXXFLAGS_RELEASE += -MT #定义编译选项 #QT_DEPRECATED_WARNINGS表示当Qt的某些功能被标记为过时的,那么编译器会发出警告 DEFINES += QT_DEPRECATED_WARNINGS #指定编译器选项和项目配置 CONFIG += c++11 CONFIG += warn_on #告诉qmake要把编译器设置为输出警告信息的 CONFIG += precompile_header #可以在项目中使用预编译头文件的支持 #预编译头文件路径 PRECOMPILED_HEADER = $$PWD/stable.h #disable C4819 warning win32:QMAKE_CXXFLAGS_WARN_ON += -wd4819 win32:QMAKE_CXXFLAGS += /FS #win32:QMAKE_CXXFLAGS += /utf-8 #避免VC编译器关于fopen等应使用fopen_s的安全警告 win32:DEFINES += _CRT_SECURE_NO_WARNINGS参考文献https://blog.csdn.net/caoshangpa/article/details/51416077https://doc.qt.io/qt-5/qmake-variable-reference.html  Qt官网.pro文件的变量清单,多关注QMAKE_CXXFLAGS

Halcon怎么处理32位的真彩色图?

原图需要先分割下通道(RGBA)再合成(RGB),针对RGB进行处理。* 读图像 read_image (Image, 'D:/autocad.png') * 获取图像宽高 get_image_size (Image, Width, Height) dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_display (Image) * 彩色转灰度图 count_channels (Image, Channels) if (Channels == 3) rgb1_to_gray (Image, Image) endif * 真彩色转灰度图 if (Channels == 4) decompose4 (Image, ImageR, ImageG, ImageB, ImageA) compose3 (ImageR, ImageG, ImageB, MultiChannelImage) rgb1_to_gray (MultiChannelImage, Image) endif

halcon readimage不支持中文路径?

Halcon v17.x之前的软件版本都不支持中文路径。Hdevelop环境下没问题,但是VC++下会报异常。read_image (Image, '我是中文.jpg') bool HalconImageWnd::readImage(const char *ch) //HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(false); //HString::FromLocal8Bit(ch); m_image.ReadImage(ch); m_image.GetImageSize(&m_width, &m_height); catch (...) qDebug("readImage error"); return false; }从Halcon v18.x开始支持中文路径,但是要事先调用下面算子来进行设置支持中文解析:将本地8位编码的字符串传递给HALCON C或HALCON/C++时,必须更改接口默认编码HALCON /C调用HalconCpp::SetHcInterfaceStringEncodingIsUtf8(false);HALCON/C++调用HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(false);或传递给HALCON的字符串使用合适的转换函数,例如HString::FromLocal8Bit(ch);---参考文献C:/Program Files/MVTec/HALCON-19.11-Progress/doc/html/manuals/programmers_guide/programmers_guide_0035.html7.4   Writing a Program with non-ASCII Charactersset_system ('filename_encoding', 'utf8')

Qt .pro文件之defineReplace函数的用法,实现lib文件名自动添加后缀“d“

本篇讲解在Qt的.pro文件使用defineReplace函数。1、先看官网的说明文档https://doc.qt.io/qt-5/qmake-language.html#replace-functions1.1 语法使用defineReplace函数定义func函数defineReplace(func) {}1.2 func传参$$func(11, 22, 33)1.3 函数返回值无论是返回什么值都需要括号。可以忽略不写。return (Hello world!)1.4 func捕获参数(1到N)defineReplace(func) {ARG1 = $$1ARG2 = $$2ARG3 = $$3}2、举例说明2.1 新建一个公共的pri文件,想让debug生成的库文件名后缀+d,可以通过defineReplace函数来实现:common.pri defineReplace(qtLibraryName) { unset(LIBRARY_NAME) LIBRARY_NAME = $$1 CONFIG(debug, debug|release) { !debug_and_release|build_pass { mac:RET = $$member(LIBRARY_NAME, 0)_debug else:win32:RET = $$member(LIBRARY_NAME, 0)d isEmpty(RET):RET = $$LIBRARY_NAME return($$RET) #指定生成的临时文件放置的目录 MOC_DIR = temp/moc RCC_DIR = temp/rcc UI_DIR = temp/ui OBJECTS_DIR = temp/obj #指定生成的应用程序放置的目录 IDE_SOURCE_TREE = $$PWD #.pro或.pri文件所在的位置 IDE_BUILD_TREE = $$IDE_SOURCE_TREE/../ win32:CONFIG(debug, debug|release){ contains(DEFINES, WIN64) { DESTDIR = $$IDE_BUILD_TREE/_debug64 } else { DESTDIR = $$IDE_BUILD_TREE/_debug86 } else:win32:CONFIG(release, debug|release){ contains(DEFINES, WIN64) { DESTDIR = $$IDE_BUILD_TREE/_release64 } else { DESTDIR = $$IDE_BUILD_TREE/_release86 macx:CONFIG(debug, debug|release){ DESTDIR = $$IDE_BUILD_TREE/_debug64 } else:macx:CONFIG(release, debug|release){ DESTDIR = $$IDE_BUILD_TREE/_release64 }2.2 新建一个动态库项目,pro文件这样写:include(../common.pri)QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTEMPLATE = libTARGET = $$qtLibraryName(ribbonTabbar)如此一来,debug生成的lib文件名就是ribbonTabbard.lib和ribbonTabbard.dll,自动添加了后缀"d"2.3 最后新建一个exe主程序项目,想引入该动态库的话,可以在pro文件这样写:include(../common.pri)IDE_LIBRARY_PATH = $${DESTDIR}#大写的L表示路径;小写的l表示库文件LIBS += -L$${IDE_LIBRARY_PATH}LIBS *= -l$$qtLibraryName(ribbonTabbar)LIBS *= 和LIBS += 是同样的意思。-L表示后面跟的是一个文件夹,工程会将这个目录加入库文件搜索路径中。 -l表示后面跟的是一个库文件的名字。不论后缀是.lib、.dll、.so、.a,都不需要加上后缀名,直接用库的点分号前面部分名字即可。2.4 32位和64位区分contains(DEFINES, 32bit) { INCLUDEPATH += $$PWD/include } else { INCLUDEPATH += $$PWD/include64 contains(DEFINES, WIN64) { INCLUDEPATH += $$PWD/include64 } else { INCLUDEPATH += $$PWD/include }3、姊妹篇欢迎访问姊妹篇《Qt Creator指定临时文件生成目录(MOC_DIR/RCC_DIR等)和PWD/OUT_PWD/.pro官方文档》欢迎访问姊妹篇《关于Qt Creator项目中.pro文件中的相对路径》

Qt单例:Qt有专门的宏Q_GLOBAL_STATIC,用来实现线程安全的单例模式

Qt本身就提供了专门的宏 Q_GLOBAL_STATIC。通过这个宏不但定义简单,还可以获得线程安全性。1、先看官方文档https://doc.qt.io/qt-5/qglobalstatic.htmlhttps://doc.qt.io/qt-5/threads-reentrancy.html2、再看使用方法Q_GLOBAL_STATIC(Type, VariableName)Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments)3、举例说明rule.h#ifndef RULE_H #define RULE_H #include <QGlobalStatic> #define RULE Rule::instance() class Rule public: Rule() {} virtual ~Rule() {} public: static Rule* instance(); public: void test(); #endif // RULE_Hrule.cpp#include "rule.h" Q_GLOBAL_STATIC(Rule, rule) Rule* Rule::instance() return rule(); void Rule::test() //todo }在任何地方,引用头文件 include "rule.h"就可以Rule::instance()->test();或者使用宏RULE->test();---参考文献https://www.cnblogs.com/findumars/p/10392770.htmlhttp://qtdebug.com/qtbook-singleton/引申阅读https://doc.qt.io/qt-5/qthreadpool.html Qt线程池https://doc.qt.io/qt-5/qsharedpointer.html Qt 智能指针https://doc.qt.io/QtMQTT/index.html Qt Mqtthttps://wiki.qt.io/QtDesignStudio

Qt之流式布局QFlowlayout

QFlowlayout简介QFlowLayout,流动布局,实现了处理不同窗口大小的布局。根据应用窗口的宽度来进行控件放置的变化。从网上找来的效果图https://ucc.alicdn.com/images/user-upload-01/20200413092618885.gifQt官方源码详情参见Qt官方的例子:https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.htmlQt安装路径下可以找到源码:F:\Qt\Qt5.12.8\Examples\Qt-5.12.8\widgets\layouts\flowlayoutF:\Qt\Qt5.12.8\Examples\Qt-5.12.8\widgets\graphicsview\flowlayout---参考文献https://blog.csdn.net/liang19890820/article/details/51519015https://blog.csdn.net/ly305750665/article/details/90704918

Qt使用GDI绘图(仅Windows平台)

绘图引擎Windows环境下二维绘图引擎有多种选择:GDI、GDI+、DirectDraw、Qt/QPainter、Agg、Cairo、skia、Direct2D、Direct3D、OpenGL等。GDI:微软原生的二维绘图引擎。优点:微软的全力支持,作为操作系统核心层效率方面不用担心,支持多种开发框架(含语言):WinSDK、MFC、Delphi等。缺点:不是面向C++对象组织的,使用起来较为繁琐;不支持反锯齿,不支持复杂的绘图效果(这个相对于GDI+而言)。GDI+:微软后来推出的二维绘图引擎。优点:微软的全力支持,支持多种开发框架(含语言):WinSDK、MFC、Delphi等,可以实现复杂的绘图效果,如反锯齿、路径画刷等;面向对象的架构,使用起来比较方便。缺点:绘图效率较GDI稍低,绘图交互性不如GDI(缺少GDI的支持位运算的绘图模式),开启反锯齿后效率不如Qt。如果不考虑绘图的效果,使用Win32 GDI函数直接绘图的效率大约是同样的GDI+的10倍以上。DirectDraw:从GDI、GDI+到Direct 2D的一个过渡产品,微软已明确表示不推荐使用。Qt:Qt的二维图形引擎是基于QPainter类的,绘图的效果取决于QPainter的设置。面向对象的方式组织,使用起来较为方便。Agg:C++编写的开源绘图引擎(基于GPL协议).AGG是C++编写的,因此,它不能被C语言很好地调用。由于其中使用了大量的现代标准C++语言的语法规则,包括模板、仿函数等处理 ,导致这样的库的学习过程将是痛苦的。AGG自从2006年之后就没有更新过。Cairo:C编写的开源绘图引擎(基于LGPL协议),大名鼎鼎的FireFox就是用这个绘图引擎的。Cairo是非常流行的开源2D图形渲染引擎库,它支持包括X-Windos,Win32,图像,pdf在内的各种输出设备。目前,Cairo已被广泛的使用在多个平台上来渲染图形界面,包括Firefox/Webkit-EFL/GTK+/Poppler/Qt等等。Qt的QPainter提供的抗锯齿效果没有cairo的好,在理想情况下,cairo的用户可以在打印机和屏幕上获得非常接近的输出效果。cairo 是用 C 编写的,但是为大多数常用的语言提供了绑定。选用 C 语言有助于创建新的绑定,同时在进行 C 语言调用时可以提供高性能。应该特别注意 Python 绑定,它支持快速原型开发,而且降低了学习 cairo 绘图 API 的门槛。 Cairo的绘图效率是接近GDI/GDIPlus的。经过优化算法,可以做到完全忽略绘图效率上的差别。此外,gtk不如qt流行,Qt支持cairo。Skia:Google的Android的绘图引擎。它是一个C++的开源2D向量图形处理函数库,包括字型、坐标转换、位图等等。skia相当于轻量级的Cairo(Cairo是矢量图形库)。Direct2D:微软在WindowsVista及之后的Windows版本推出的意在取代GDI、GDI+的二维绘图引擎,支持硬件加速。Direct 2D是微软在后XP时代开发的开发二维绘图引擎。微软出于兼容性的考虑还会继续对GDI、GDI+进行支持,但毫无疑问微软的策略是要Direct 2D取代GDI和GDI+的,因此在WindowsVista及其之后的Windows上进行二维绘图开发,建议是直接使用Direct2D。Direct 2D支持硬件加速,在绘图效率应有一定程度的提升。Direct3D:微软开发的3D绘图引擎。OpenGL:SGI开发的3D绘图引擎。OpenGL的优势是三维绘图,不建议用来二维绘图,因为OpenGL在二维一些操作并不合适,如二维中的点、线捕捉、自定义图例的添加、打印的支持等等。更详细的内容请见我的另一篇博文:https://blog.csdn.net/libaineu2004/article/details/105308235使用GDI取代QPainterQPainter在高频绘画的使用CPU占用较高,我们可以使用GDI绘图。由于没有复杂的抗锯齿处理,GDI绘图效率非常不错。GDI因为是使用GPU绘图,会减少CPU占用。因为Qt是通过repaint和update事件触发paintEvent绘图,其他绘图会被覆盖,所以需要以下方法实现GDI绘图:在需要绘图的Widget构造函数写setAttribute(Qt::WA_PaintOnScreen, true);重写该Widget的QPaintEngine * paintEngine()函数返回nullptr;在绘图函数用GDI绘图,不要在paintEvent实现,因为刷新会慢,在自己主动调用的函数里写:HWND hwnd; hwnd = (HWND)this->winId(); HDC labelDC = GetDC(hwnd);//取得窗体句柄 QImage image(imageRaw.get(), m_w, m_h, QImage::Format_Grayscale8);//imageRaw是std::shared_ptr<unsigned char>类型,m_w和m_h是图像宽高 QPixmap pixmap = QPixmap::fromImage(image); HBITMAP bitMap = toHBITMAP(pixmap);//通过一系列转换得到HBITMAP位图 HDC hdcsource1 = CreateCompatibleDC(labelDC);//创建后备显示缓冲 SelectObject(hdcsource1, bitMap); BitBlt(labelDC, 0, 0, m_w, m_h, hdcsource1, 0, 0, SRCCOPY);//将后备缓冲显示到屏幕 ReleaseDC(hwnd, labelDC); DeleteObject(hdcsource1); DeleteObject(bitMap);Qt绘图获取HDCQt使用GDI绘图关键在于获取HDC,对于Qt5来说,有3种方法:1、使用gui-privatepro或pri文件中增加 QT += gui-private#include <qpa/qplatformnativeinterface.h>QPlatformNativeInterface *fooPlatformNativeInterface=  QGuiApplication::platformNativeInterface();QBackingStore *fooBackingStore = this->topLevelWidget()->backingStore();HDC fooNRFWGetDC = static_cast<HDC>(fooPlatformNativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), fooBackingStore));这个方法不需要releaseDC。此方法使用了Qt官方不推荐使用的 gui-private,并且在整个窗口绘图,没有限制。2、强行使用GetDCpro或pri文件中增加 LIBS += -lgdi32 -luser32#include <windows.h>HWND hwnd = (HWND)this->window()->winId();HDC hdc = GetDC(hwnd);ReleaseDC(hwnd, dhc);方法2只适用于顶层窗体。此方法在整个窗口绘图,没有限制。3、使用QtWinpro或pri文件中增加 QT += winextras#include <QtWin> HDC hdcScreen = GetDC(NULL); HDC hdc = CreateCompatibleDC(hdcScreen); HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, rectForMap.width(), rectForMap.height()); SelectObject(hdc, hbm); QImage img = QtWin::imageFromHBITMAP(hdc, hbm, rectForMap.width(), rectForMap.height()); //释放GDI资源 DeleteObject(hbm); DeleteDC(hdc); ReleaseDC(nullptr, hdcScreen);该方法是Qt5.2后的一种新的使用GDI绘图的方法,在Qt5.2中,新增了命名空间QtWin,推荐使用!参考文献https://blog.csdn.net/wwwwxhh/article/details/79461668https://blog.csdn.net/ssitu/article/details/54615746

Python开源游戏,《植物大战僵尸》

python开发植物大战僵尸游戏https://github.com/371854496/pygamehttps://segmentfault.com/a/1190000019418065a simple PlantsVsZombies gamehttps://github.com/marblexu/PythonPlantsVsZombies该项目使用json文件存储关卡数据(例如僵尸的位置和时间,背景信息),并且支持白天状态功能和夜间状态切换功能。实施植物有:向日葵,豌豆,wallnut,snowpeashooter,cherrybomb,threepeashooter,剁碎,puffshroom,potatomine,穗状花序,scaredyshroom,南瓜,scaredyshroom,墨西哥胡椒,sunShroom,iceShroom,hypnoShroom。实施僵尸有:僵尸,鞭毛僵尸,锥头僵尸,水头僵尸,报纸僵尸。---https://www.pygame.org/

halcon模板匹配实践(2)算子find_shape_model里的参数Row, Column, Angle含义是什么?

Halcon模板匹配算子find_shape_model里的参数Row, Column, Angle(单位:弧度)含义是什么?find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)先看官方文档怎么说The position and rotation of the found instances of the model is returned in Row, Column, and Angle. Additionally, the score of each found instance is returned in Score. 找到的模型实例的位置和旋转以行,列和角度返回。 此外,每个找到的实例的分数都在Score中返回。 find_shape_model(Image : : //搜索图像 ModelID, //模板句柄 AngleStart, // 搜索时的起始角度 AngleExtent, //搜索时的角度范围,必须与创建模板时的有交集 MinScore, //最小匹配值,输出的匹配的得分Score 大于该值 NumMatches, //定义要输出的匹配的最大个数 MaxOverlap, //当找到的目标存在重叠时,且重叠大于该值时选择一个好的输出 //如果MaxOverlap=0, 找到的目标区域不能存在重叠, 如果MaxOverla p=1,所有找到的目标区域都要返回。 SubPixel, //计算精度的设置,五种模式,多选2,3 NumLevels, //搜索时金字塔的层数 Greediness : //贪婪度,搜索启发式,一般都设为0.9,越高速度快,容易出现找不到的情况 //0安全慢;1块不稳定;其他就是介于中间值 Row,Column, Angle, Score) //输出匹配位置的行和列坐标、角度、得分。再来做个小实验画图举例说明,Row, Column, Angle到底指的是什么距离?1、已知图1和图2。小实验需要从图1取出模板,然后在图2找到相同的物体。2、从图1框选ROI,ROI的像素中心点是B,ROI就是模板。3、使用find_shape_model算子,在图2找到了物品,算子返回了Row, Column, Angle三个参数。4、如下图所示,A,B,C点三者的对应关系是求出来了。A是图1左上角的起点;B是ROI的像素中心点,也是图2的起点;C是匹配到的物体像素中心点。A与B之间的宽和高分别是(row1,col1)B与C之间的宽和高分别是(row2,col2)结论:find_shape_model算子,其返回值Row, Column参数指的就是row2和col2。最后来看看halcon源码的实现*读图1 read_image (Image1, '1.jpg') *获取图像宽高 get_image_size (Image1, Width, Height) dev_open_window_fit_image (Image1, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_display (Image1) *彩色转灰度图 count_channels (Image1, Channels) if (Channels == 3) rgb1_to_gray (Image1, Image1) *真彩色转灰度图 elseif (Channels == 4) decompose4 (Image1, ImageR, ImageG, ImageB, ImageA) compose3 (ImageR, ImageG, ImageB, MultiChannelImage) rgb1_to_gray (MultiChannelImage, Image1) endif *从图1选取ROI,建立模板 draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2) gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2) area_center (Rectangle, Area, RowRef, ColumnRef) reduce_domain (Image1, Rectangle, ImageReduced) create_shape_model (ImageReduced, 'auto', 0, rad(180), 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID) get_shape_model_contours (ShapeModel, ModelID, 1) read_image (Image2, '2.jpg') *模板匹配 find_shape_model (Image2, ModelID, 0, rad(180), 0.1, 1, 0.5, 'least_squares', 0, 0.7, Row, Column, Angle, Score) if (|Score| > 0) dev_set_color ('yellow') dev_clear_window() vector_angle_to_rigid (0, 0, 0, Row, Column, Angle, MovementOfObject) affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, MovementOfObject) dev_display (ImageNew1) dev_display (ModelAtNewPosition) endif代码里使用了仿射变换:1、Halcon二维仿射变换,严格按照平移-->旋转-->缩放的先后顺序实施;2、一切以ROI模板的中心点(即鼠标选取的模板图像的像素中心,上文中描述的点B)为零点,。图2找到的任何物品,都是以ROI的中心点为基准的;3、图2,ROI模板从B点出发,平移(Row,Column),达到C点,再旋转Angle,最后缩放(如果是find_scaled_shape_model算子)。如此就可以找到物品的准确位置。

halcon视觉缺陷检测系列(3)频域和空间域转换的方法详解

3、木板划痕检测*http://www.ihalcon.com/read-13031-1.html *缺陷检测,将木板的划痕提取出来 dev_update_off () dev_close_window () read_image (Image, '缺陷检测木板划痕提取.jpg') *彩色转灰度图 count_channels (Image, Channels) if (Channels == 3 or Channels == 4) rgb1_to_gray (Image, Image) endif get_image_size (Image, Width, Height) dev_open_window_fit_size (0, 0, Width, Height, -1, -1, WindowHandle) dev_display (Image) *傅里叶变换去背景 fft_generic (Image, ImageFFT, 'to_freq', -1, 'sqrt', 'dc_center', 'complex') gen_rectangle2 (Rectangle1, 308.5, 176.56, rad(-0), 179.4, 7.725) gen_rectangle2 (Rectangle2, 306.955, 175, rad(-90), 180.765, 4.68) union2 (Rectangle1, Rectangle2, UnionRectangle) paint_region (UnionRectangle, ImageFFT, ImageResult, 0, 'fill') fft_generic (ImageResult, ImageFFT1, 'from_freq', 1, 'sqrt', 'dc_center', 'byte') *提取划痕 threshold (ImageFFT1, Regions, 5, 240) connection (Regions, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 20, 99999) union1 (SelectedRegions, RegionUnion) dilation_rectangle1 (RegionUnion, RegionDilation, 5, 5) connection (RegionDilation, ConnectedRegions1) select_shape (ConnectedRegions1, SelectedRegions1, ['width','height'], 'and', [30,15], [150,100]) dilation_rectangle1 (SelectedRegions1, RegionDilation1, 11, 11) union1 (RegionDilation1, RegionUnion1) skeleton (RegionUnion1, Skeleton) dev_set_color ('red') dev_display (Image) dev_display (Skeleton)halcon官方自带的例子detect_indent_fft.hdevdetect_mura_defects_texture.hdev官方例子detect_indent_fft,使用了差分两个高斯滤波器detect_indent_fft.hdev * Optimize the fft speed for the specific image size optimize_rft_speed (Width, Height, 'standard') * Construct a suitable filter by combining two gaussian * filters Sigma1 := 10.0 Sigma2 := 3.0 gen_gauss_filter (GaussFilter1, Sigma1, Sigma1, 0.0, 'none', 'rft', Width, Height) gen_gauss_filter (GaussFilter2, Sigma2, Sigma2, 0.0, 'none', 'rft', Width, Height) sub_image (GaussFilter1, GaussFilter2, Filter, 1, 0) * Process the images iteratively NumImages := 11 for Index := 1 to NumImages by 1 * Read an image and convert it to gray values read_image (Image, 'plastics/plastics_' + Index$'02') rgb1_to_gray (Image, Image) * Perform the convolution in the frequency domain rft_generic (Image, ImageFFT, 'to_freq', 'none', 'complex', Width) convol_fft (ImageFFT, Filter, ImageConvol) rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width)姊妹篇halcon视觉缺陷检测常用的6种方法参考文献微信公众号:机器视觉那些事儿《Halcon机器视觉算法原理与编程实战》杨青

halcon视觉缺陷检测系列(2)频域和空间域转换的方法详解

理论基础一、频率特征是图像的灰度变化特征,低频特征是灰度变化不明显,例如图像整体轮廓,高频特征是图像灰度变化剧烈,如图像边缘和噪声。一个重要的经验结论:低频代表图像整体轮廓,高频代表了图像噪声,中频代表图像边缘、纹理等细节。什么时候使用傅里叶变换进行频域分析?具有一定纹理特征的图像,纹理可以理解为条纹,如布匹、木板、纸张等材质容易出现。 需要提取对比度低或者信噪比低的特征。 图像尺寸较大或者需要与大尺寸滤波器进行计算,此时转换至频域计算,具有速度优势。因为空间域滤波为卷积过程(加权求和),频域计算直接相乘。二、在halcon中,使用频域进行检测,有两个步骤是比较关键的:一个是生成合适的滤波器;一个是空间域和频域之间的转换。生成滤波器主要有如下算子:gen_std_bandpass,gen_sin_bandpass,gen_gauss_filter,gen_mean_filter, gen_derivative_filter,gen_bandpass, gen_bandfilter, gen_highpass, gen_lowpass空间域和频域之间的转换,主要有如下两个关键算子:rft_genericfft_generic这两个算子的共同点:这两个算子都是进行快速傅里叶变换的算子这两个算子都可以进行空间域-》频域和频域-》空间域的变换,只需要针对参数Direction分别进行选择,'to_freq'是进行的是空间域-》频域的变换,'from_freq'是频域-》空间域的变换。针对参数ResultType,如果是'to_freq',那么ResultType一般选择'complex';如果是'from_freq',ResultType一般选择'byte'(灰度图像)。这两个算子的不同点: rft_generic算子的输入图像是实值函数,fft_generic的输入图像是复数函数;从输出的结果来看,rft_generic只需要计算和存储了左半边的复数图像信息就可以了,因为右半边是共轭对称的。因此从最终的输出我们可以看到,只有左上和左下有DC成分。而fft_generic如果设定的是原点在左上角,那么就会在四个角上有DC成分。fft_generic算子可以通过参数Mode设置原点的位置:如果设置的是'dc_edge',那么原点在左上角;如果设置的是'dc_center',那么就会将原点平移到中心位置。fft_generic算子一般会设置为'dc_center'。对于rft_generic算子,因为没有设置项,所以默认原点位置为左上角。针对同一个图像,进行空间域-》频域、频域-》空间域的转换的时候,如果使用的是rft_generic算子,那么两个转换就都使用该算子;如果使用的是fft_generic算子,那么两个转换也都使用该算子,在对同一个图像进行空间域和频域的相互转换时,不要交叉使用这两个算子。当然,从空间域到频域的转换,也可以使用算子fft_image,这个算子也是快速傅里叶变换,其实际效果相当于:fft_generic(Image,ImageFFT,'to_freq',-1,'sqrt','dc_center','complex')举例说明1、检测布料表面划痕*《Halcon机器视觉算法原理与编程实战》16-1 *清空当前窗口 dev_close_window () *读取测试图像 read_image (Image, 'data/cloth1') *获取图像的宽 get_image_size (Image, Width, Height) *创建显示窗口,并设置窗口及绘制参数 dev_open_window_fit_size (0, 0, Width, Height, -1, -1, WindowHandle) dev_display (Image) dev_set_draw ('margin') dev_set_line_width (3) dev_set_color ('red') *创建一个高斯滤波器,用于将傅里叶转换后的图像进行滤波 gen_gauss_filter (GaussFilter, 3.0, 3.0, 0.0, 'none', 'rft', Width, Height) *开始检测 *将测试图像转化为单通道的灰度图像 rgb1_to_gray (Image, ImageGray) *对灰度图像进行颜色反转 invert_image (ImageGray, ImageInvert) *对反转后的图像进行傅里叶变换 rft_generic (ImageInvert, ImageFFT, 'to_freq', 'none', 'complex', Width) *对傅里叶图像做卷积,使用之前创建的高斯滤波器作为卷积核 convol_fft (ImageFFT, GaussFilter, ImageConvol) *将卷积后的傅里叶图像还原为空间域图像。可见图像的突变部分得到了增强 rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width) *设置提取线条的参数 calculate_lines_gauss_parameters (17, [25,3], Sigma, Low, High) *将图像中的有灰度差异的线条提取出来 lines_gauss (ImageFiltered, Lines, Sigma, Low, High, 'dark', 'true', 'gaussian', 'true') *将提取出的结果显示出来 dev_display (Image) dev_display (Lines)2、傅里叶变换之划痕检测*微信公众号--机器视觉那些事儿 *检测-FFT傅里叶变换之划痕检测 *对于检测表面是具有一定纹理的比如:布匹、皮革、塑料等,针对这一类表面的检测就不能单纯依靠帧差或者背景差来完成, *这种情况下,通过将图像变换到频域进行处理,提取缺陷分量后反变换到时域,然后通过Blob分析获得缺陷的具体位置。 *重点说明: *频域处理部分的过程为: *1)先生成一个滤波器,此处生成的是正弦形状的带通滤波,使用的算子为gen_sin_bandpass。 *2)然后再进行图像的傅里叶变换,使用的算子为rft_generic,此处需要注意参数的使用。 *3)使用之前的滤波器,对图像在频域进行卷积计算,从而增强高频信息。 *4)最后对图像进行傅里叶反变换,使用的算子依然是rft_generic,注意和第二步中的参数进行区分。在这一步,即得到了我们平时进行Blob分析的图像。 *之后的处理分为三部分: *1)第一部分,先进行Blob分析后,筛选掉一些杂点。然后提取出保留区域所对应的图像。 *2)第二部分进行亚像素处理,先提取出亚像素轮廓,使用的是lines_gauss算子;然后按照轮廓总长度进行轮廓筛选,从而得到划痕的亚像素轮廓。至此,已经得到划痕了。 *3)第三部分进行划痕区域的处理,先将亚像素轮廓转为区域,使用的算子是gen_region_contour_xld;得到划痕轮廓之后就可以将划痕标记出来了。 * 首先,创建合适的带通滤波 * 然后,输入图像在频域中进行傅里叶变换和滤波,以便增强高频信息 * 最后,再被转换回空间域,增强的缺陷通过形态学进行之后的处理 dev_update_off () dev_close_window () * 读图像 read_image (Image, '检测-FFT傅里叶变换之划痕检测.png') *彩色转灰度图 count_channels (Image, Channels) if (Channels == 3 or Channels == 4) rgb1_to_gray (Image, Image) endif * 翻转图像,亮变暗 暗变量 invert_image (Image, ImageInverted) * 获取图像宽高 get_image_size (Image, Width, Height) * dev_open_window (0, 0, Width, Height, 'black', WindowHandle) dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_display (Image) * Optimize the speed of the fast fourier transform * 优化快速傅里叶变换的速度 * Message := 'Optimize the speed of the fast fourier transform.' * Message[1] := 'Please wait...' * disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') * optimize_rft_speed (Width, Height, 'standard') * disp_continue_message (WindowHandle, 'black', 'true') * stop () * Enhance the scratches by filtering in the frequency domain * 通过在频域中滤波来增强划痕 * 生成具有正弦形状的带通滤波器 gen_sin_bandpass (ImageBandpass, 0.4, 'none', 'rft', Width, Height) * 对一幅图片的实部进行快速傅里叶变换的计算,将图像转为傅里叶图像 * 参数为'to_freq',输出图像为复数形式 * ImageInverted:输入的图片(输入图像需要为背景为暗,前景为亮的图像,一般需要先要将原始图像反转) * ImageFFT:傅里叶变换后输出的图片 * 'to_freq':变换方向,傅里叶变换 * 'none':变换因子的规范 * 'complex':输出图片的数据类型,输出图像为复数形式 * Width: 图像的宽 rft_generic (ImageInverted, ImageFFT, 'to_freq', 'none', 'complex', Width) * 对图片用滤波器在频域进行卷积运算 * ImageFFT: 输入的图片 * ImageBandpass:频域滤波器 * ImageConvol:计算后的输出图像 convol_fft (ImageFFT, ImageBandpass, ImageConvol) * 对滤波后的图片进行傅里叶反变换 * 参数为'from_freq',输入图像为复数形式 rft_generic (ImageConvol, Lines, 'from_freq', 'n', 'byte', Width) * Segment the scratches by using morphology * 使用形态分割划痕 * 二值化 threshold (Lines, Region, 5, 255) * 获得连通域 connection (Region, ConnectedRegions) * 特征直方图,按照面积特征选择区域 select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 5, 5000) dilation_circle (SelectedRegions, RegionDilation, 5.5) * 区域联合成一个区域 union1 (RegionDilation, RegionUnion) reduce_domain (Image, RegionUnion, ImageReduced) * 检测线条及其宽度 * 输出亚像素直线轮廓 lines_gauss (ImageReduced, LinesXLD, 0.8, 3, 5, 'dark', 'false', 'bar-shaped', 'false') * 联合直线亚像素轮廓 union_collinear_contours_xld (LinesXLD, UnionContours, 40, 3, 3, 0.2, 'attr_keep') * 按照轮廓的总长度来选择亚像素轮廓 select_shape_xld (UnionContours, SelectedXLD, 'contlength', 'and', 15, 1000) * 由亚像素轮廓生成区域 gen_region_contour_xld (SelectedXLD, RegionXLD, 'filled') * 区域联合 union1 (RegionXLD, RegionUnion) dilation_circle (RegionUnion, RegionScratches, 10.5) * Display the results * 显示标记出来的的直线划痕 dev_set_draw ('margin') dev_set_line_width (3) dev_set_colored (12) dev_display (Image) dev_display (RegionScratches)

Qt信号槽使用结构体作为参数:Q_DECLARE_METATYPE和qRegisterMetaType的作用

问题由来定义一个结构体struct myStruct{  int a;  float b;};通过信号槽传递该结构体connect(this, SIGNAL(m_signal(myStruct)), this, SLOT(m_slot(myStruct)));这样做是行不通的,正确的做法:通过Q_DECLARE_METATYPE声明自定义的结构体struct myStruct{  int a;  float b;};Q_DECLARE_METATYPE(myStruct);然后以QVariant代替自定义的结构体connect(this, SIGNAL(m_signal(QVariant)), this, SLOT(m_slot(QVariant)));在发射信号前,将自定义结构体打包为QVariantmyStruct mstruct;QVariant data;data.setValue(mstruct);emit signal_child(data);在槽函数中,解析QVariantmyStruct mstruct = data.value<myStruct>();注册元类型信号可以带参数,参数的类型,必须是元对象系统能够识别的类型, 即元类型。下面这几个类型是自动注册的,不需要使用Q_DECLARE_METATYPE这个宏:1.QObject继承下来的子类的指针;2.QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T>这些T都是自动注册的;3.QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> T1,和T2都是自动注册的;4.QPointer<T>, QSharedPointer<T>, QWeakPointer<T>这3个T必须是QObject的子类;5.枚举类型要用Q_ENUM or Q_FLAG;6.拥有Q_GADGET宏的类。例如:自定义结构体,connect想通过结构体参数来传递struct _ColorBalance bool preserve_luminosity; int cyan_red[3]; int magenta_green[3]; int yellow_blue[3]; signals: void state_changed(_ColorBalance *color_balance); connect(this, &ColorBalance::state_changed, pic, &Picture::ColorBalance);Qt已经将大部分常用的基础类型,都注册进了元对象系统,可以在QMetaType类中看到。通常写的继承于QObject的子类,本身已经附带了元信息,可以直接在信号-槽中使用。不是继承于QObject的结构体、类等自定义类型,可以通过Q_DECLARE_METATYPE宏 或者 qRegisterMetaType函数进行注册,之后就可以在信号-槽中使用。官方文档https://wiki.qt.io/New_Signal_Slot_Syntaxhttps://woboq.com/blog/new-signals-slots-syntax-in-qt5.htmlhttps://woboq.com/blog/how-qt-signals-slots-work.htmlhttps://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.htmlhttps://doc.qt.io/qt-5/signalsandslots-syntaxes.htmlhttps://doc.qt.io/qt-5/qmetatype.htmlint qRegisterMetaType()Call this function to register the type T. T must be declared with Q_DECLARE_METATYPE(). Returns the meta type Id. Example: int id = qRegisterMetaType<MyStruct>(); This function requires that T is a fully defined type at the point where the function is called. For pointer types, it also requires that the pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able to register pointers to forward declared types. After a type has been registered, you can create and destroy objects of that type dynamically at run-time. To use the type T in QVariant, using Q_DECLARE_METATYPE() is sufficient. To use the type T in queued signal and slot connections, qRegisterMetaType<T>() must be called before the first connection is established. Also, to use type T with the QObject::property() API, qRegisterMetaType<T>() must be called before it is used, typically in the constructor of the class that uses T, or in the main() function. Q_DECLARE_METATYPE(Type) This macro makes the type Type known to QMetaType as long as it provides a public default constructor, a public copy constructor and a public destructor. It is needed to use the type Type as a custom type in QVariant. This macro requires that Type is a fully defined type at the point where it is used. For pointer types, it also requires that the pointed to type is fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to register pointers to forward declared types. Ideally, this macro should be placed below the declaration of the class or struct. If that is not possible, it can be put in a private header file which has to be included every time that type is used in a QVariant. Adding a Q_DECLARE_METATYPE() makes the type known to all template based functions, including QVariant. Note that if you intend to use the type in queued signal and slot connections or in QObject's property system, you also have to call qRegisterMetaType() since the names are resolved at runtime. This example shows a typical use case of Q_DECLARE_METATYPE(): struct MyStruct int i; Q_DECLARE_METATYPE(MyStruct) If MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro has to be outside the namespace: namespace MyNamespace Q_DECLARE_METATYPE(MyNamespace::MyStruct) Since MyStruct is now known to QMetaType, it can be used in QVariant: MyStruct s; QVariant var; var.setValue(s); // copy s into the variant // retrieve the value MyStruct s2 = var.value<MyStruct>(); Some types are registered automatically and do not need this macro: Pointers to classes derived from QObject QList<T>, QVector<T>, QQueue<T>, QStack<T>, QSet<T> or QLinkedList<T> where T is a registered meta type QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are registered meta types QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject Enumerations registered with Q_ENUM or Q_FLAG Classes that have a Q_GADGET macro

CONFIG += c++11 # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ HalconImageWnd.cpp \ ROI.cpp \ ROIArc.cpp \ ROICircle.cpp \ ROIController.cpp \ ROILine.cpp \ ROIPolygon.cpp \ ROIPolyline.cpp \ ROIRectangle.cpp \ ROIRectangle2.cpp \ main.cpp \ mainwindow.cpp HEADERS += \ HalconImageWnd.h \ ROI.h \ ROIArc.h \ ROICircle.h \ ROIController.h \ ROILine.h \ ROIPolygon.h \ ROIPolyline.h \ ROIRectangle.h \ ROIRectangle2.h \ mainwindow.h \ stable.h #调试输出 #DEFINES += QT_MESSAGELOGCONTEXT DEFINES += QT_MESSAGELOGCONTEXT CONFIG(release, debug|release){ DEFINES += QT_NO_WARNING_OUTPUT DEFINES += QT_NO_DEBUG_OUTPUT #指定生成的临时文件放置的目录 MOC_DIR = temp/moc RCC_DIR = temp/rcc UI_DIR = temp/ui OBJECTS_DIR = temp/obj #指定编译器选项和项目配置 CONFIG += c++11 CONFIG += warn_on #告诉qmake要把编译器设置为输出警告信息的 #CONFIG += warn_off #不要警告输出 CONFIG += precompile_header #可以在项目中使用预编译头文件的支持 #预编译头文件路径 PRECOMPILED_HEADER = $$PWD/stable.h #disable C4819 warning win32:QMAKE_CXXFLAGS_WARN_ON += -wd4819 win32:QMAKE_CXXFLAGS += /FS #QMAKE_CXXFLAGS += /utf-8 #避免VC编译器关于fopen等应使用fopen_s的安全警告 win32:DEFINES += _CRT_SECURE_NO_WARNINGS #指定生成的应用程序放置的目录 CONFIG(debug, debug|release){ contains(DEFINES, WIN64) { DESTDIR = ../_debug64 } else { DESTDIR = ../_debug32 } else { contains(DEFINES, WIN64) { DESTDIR = ../_release64 } else { DESTDIR = ../_release32 macx:CONFIG(debug, debug|release){ DESTDIR = ../bind } else:macx:CONFIG(release, debug|release){ DESTDIR = ../bin message($$PWD) message($$DESTDIR) #Halcon Configuration isEmpty(MY_HALCON_PATH) { win32:MY_HALCON_PATH = "D:/My Resources/ImageProcessingLibrary/halcon/" #注意斜杆的方向;引号; macx:MY_HALCON_PATH = none message($$MY_HALCON_PATH) #头文件包含路径 win32 { INCLUDEPATH += $${MY_HALCON_PATH}/include/ INCLUDEPATH += $${MY_HALCON_PATH}/include/halconcpp DEPENDPATH += $${MY_HALCON_PATH}/include/ #库文件包含路径 win32 { contains(QT_ARCH, i386) { message("32-bit") #Windows x86 (32bit) specific build here MY_HALCON_LIBS_PATH = $${MY_HALCON_PATH}/lib/x86sse2-win32 } else { message("64-bit") #Windows x64 (64bit) specific build here MY_HALCON_LIBS_PATH = $${MY_HALCON_PATH}/lib/x64-win64 message($$MY_HALCON_LIBS_PATH) #依赖库的名称 win32:CONFIG(debug, debug|release): { LIBS += -L$${MY_HALCON_LIBS_PATH} -lhalcon LIBS += -L$${MY_HALCON_LIBS_PATH} -lhalconcpp else:win32:CONFIG(release, debug|release):{ LIBS += -L$${MY_HALCON_LIBS_PATH} -lhalcon LIBS += -L$${MY_HALCON_LIBS_PATH} -lhalconcpp else:unix:{ # MacOS specific settings. Note that while dyld will search under # /Library/Frameworks by default, the preprocessor/compiler/linker will not # and need to be told explicitly. macx { QMAKE_CXXFLAGS += -F/Library/Frameworks QMAKE_LFLAGS += -F/Library/Frameworks LIBS += -framework HALCONCpp # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target #pro文件的参考文档 #https://doc.qt.io/qt-5/qmake-variable-reference.html Qt+OpenCV#------------------------------------------------- # Project created by QtCreator 2019-08-29T10:43:54 #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = qt_opencv_demo TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += main.cpp\ Widget_op.cpp \ mylabel.cpp HEADERS += \ mylabel.h \ Widget_op.h \ stable.h FORMS += Widget_op.ui #指定生成的临时文件放置的目录 MOC_DIR = temp/moc RCC_DIR = temp/rcc UI_DIR = temp/ui OBJECTS_DIR = temp/obj #指定编译器选项和项目配置 CONFIG += c++11 CONFIG += warn_on #告诉qmake要把编译器设置为输出警告信息的 #CONFIG += warn_off #不要警告输出 CONFIG += precompile_header #可以在项目中使用预编译头文件的支持 #预编译头文件路径 PRECOMPILED_HEADER = $$PWD/stable.h #disable C4819 warning win32:QMAKE_CXXFLAGS_WARN_ON += -wd4819 win32:QMAKE_CXXFLAGS += /FS #避免VC编译器关于fopen等应使用fopen_s的安全警告 win32:DEFINES += _CRT_SECURE_NO_WARNINGS #指定生成的应用程序放置的目录 win32:CONFIG(debug, debug|release){ contains(DEFINES, WIN64) { DESTDIR = ../_debug64 } else { DESTDIR = ../_debug32 } else:win32:CONFIG(release, debug|release){ contains(DEFINES, WIN64) { DESTDIR = ../_release64 } else { DESTDIR = ../_release32 macx:CONFIG(debug, debug|release){ DESTDIR = ../bind } else:macx:CONFIG(release, debug|release){ DESTDIR = ../bin message($$PWD) message($$DESTDIR) #Opencv Configuration isEmpty(MY_OPENCV_PATH) { win32:MY_OPENCV_PATH = "D:/My Resources/ImageProcessingLibrary/opencv/" #注意斜杆的方向;引号; macx:MY_OPENCV_PATH = "/Users/firecat/opencv4.2.0" message($$MY_OPENCV_PATH) #头文件包含路径 win32 { INCLUDEPATH += $${MY_OPENCV_PATH}/include/ DEPENDPATH += $${MY_OPENCV_PATH}/include/ macx { INCLUDEPATH += $${MY_OPENCV_PATH}/include/opencv4 DEPENDPATH += $${MY_OPENCV_PATH}/include/opencv4 #库文件包含路径 win32 { contains(QT_ARCH, i386) { message("32-bit") #Windows x86 (32bit) specific build here MY_OPENCV_LIBS_PATH = $${MY_OPENCV_PATH}/Win32/vc15/lib } else { message("64-bit") #Windows x64 (64bit) specific build here MY_OPENCV_LIBS_PATH = $${MY_OPENCV_PATH}/x64/vc15/lib message($$MY_OPENCV_LIBS_PATH) macx { MY_OPENCV_LIBS_PATH = $${MY_OPENCV_PATH}/lib message($$MY_OPENCV_LIBS_PATH) #依赖库的名称 win32:CONFIG(debug, debug|release): {#动态库 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_calib3d420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_core420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_features2d420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_flann420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_highgui420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgcodecs420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgproc420d LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_videoio420d else:win32:CONFIG(release, debug|release):{ LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_calib3d420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_core420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_features2d420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_flann420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_highgui420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgcodecs420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgproc420 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_videoio420 else:macx:{ LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_calib3d.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_core.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_features2d.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_flann.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_highgui.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgcodecs.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_imgproc.4.2.0 LIBS += -L$${MY_OPENCV_LIBS_PATH} -lopencv_videoio.4.2.0 #pro文件的参考文档 #https://doc.qt.io/qt-5/qmake-variable-reference.html 预编译头文件stable.h//#ifndef STABLE_H //#define STABLE_H // Add C includes here #include <cmath> #include <cstdlib> #include <ctime> #include <iomanip> #include <iostream> #include <math.h> #if defined __cplusplus // Add C++ includes here #include <algorithm> #include <string.h> #include <vector> using namespace std; // Qt includes #include <QApplication> #include <QDateTime> #include <QDebug> #include <QFileDialog> #include <QGraphicsEllipseItem> #include <QGraphicsRectItem> #include <QGraphicsScene> #include <QGroupBox> #include <QHBoxLayout> #include <QImage> #include <QLabel> #include <QList> #include <QMainWindow> #include <QMenu> #include <QMessageBox> #include <QMouseEvent> #include <QPainter> #include <QPixmap> #include <QPointF> #include <QPushButton> #include <QScopedPointer> #include <QSettings> #include <QSlider> #include <QStandardItem> #include <QStandardItemModel> #include <QStyledItemDelegate> #include <QTextCodec> #include <QThread> #include <QUndoGroup> #include <QUndoStack> #include <QVBoxLayout> #include <QVector> #include <QWheelEvent> #include <QWidget> #include <qdebug.h> #include <qfiledialog.h> #include <qmath.h> //如果可以的话,请尽量不要#include <QtCore>和#include <QtGui>,因为这两个头文件涵盖了Qt所有的类,处理他们需要的时间相当长。 //#include <QtCore> //请谨慎包含 //#include <QtGui> //请谨慎包含 #include <opencv2/opencv.hpp> //using namespace cv; #ifndef max #define max(x, y) ((x) < (y) ? (y) : (x)) #define min(x, y) ((x) < (y) ? (x) : (y)) #endif //解决UTF-8编码中文乱码的问题 #ifdef _MSC_VER #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8") #pragma warning(disable : 4819) #endif // _MSC_VER >= 1600 #endif // _MSC_VER //扩展qDebug以文件行列记录信息 #define QLOG_DEBUG(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("DEBUG") \ .arg(msg); #define LWLGD //LWLG::日志开关,注释关闭打印日志 #ifdef LWLGD #define lwlgout qDebug() << "[lwlg]File" << __FILE__ << ",Line:" << __LINE__ << ">>" #else #define lwlgout #endif #endif //__cplusplus //#endif // STABLE_H 建议不要在项目中使用using namespace cv;否则会报错:error C2872: “ACCESS_MASK”: 不明确的符号 因为winnt.h里边定义了cv,它的cv空间里有一个符号叫ACCESS_MASK; opencv函数里边也定义了命名空间cv,它的cv空间里也有一个符号叫ACCESS_MASK。 那么我的项目如果同时包含这两个头文件,计算机是否知道我要调用哪个ACCESS_MASK吗? main.cpp ———————————————— 版权声明:本文为CSDN博主「libaineu2004」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/libaineu2004/article/details/105309196

若干Halcon官方自带的案例学习

2D物体识别C:\Users\Public\Documents\MVTec\HALCON-19.11-Progress\examples\hdevelop\Applications\Object-Recognition-2Dforest.hdev识别森林中的树,这个例子是主要讲解了如何通过无人机拍摄的图像识别其中的对象。smooth_image 、watersheds 等算子被应用。dem_trees.hdevroads.hdev提取道路texture.hdev查找纹理区域(树木和灌木丛)点胶质量检测apply_bead_inspection_model.hdev*此示例显示了如何使用磁珠检查来验证胶珠。 珠检查可用于检测以下错误:*-缺少粘合剂的线段*-粘合剂太多或太少的段*-胶粘剂离预定位置太远的部分* apply_bead_inspection_model要求检查图像*已与参考轮廓对齐。 在这个例子中对齐基于平面可变形匹配。https://blog.csdn.net/cashmood/article/details/104965126检查瓶口缺陷inspect_bottle_mouth.hdev圆环类缺陷检测的一种方法(极坐标变换法)https://blog.csdn.net/cashmood/article/details/104709546inspect_solar_fingers.hdev*对于太阳能行业,一个普遍的问题是太阳能电池的手指。 这个例子展示了如何使用形态学提取断指。