尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Win7下HALCON 13与VS2013、Qt 5.6.3环境配置实战指南

Win7下HALCON 13与VS2013、Qt 5.6.3环境配置实战指南 做机器视觉的上位机开发HALCON基本是绕不开的算法封装成熟、算子丰富现场调试效率高。但它的开发环境配置一直有点折磨人尤其是还在用Win7的老工控机上要同时把VS2013、Qt和HALCON串起来。我刚接手这类项目时光一个链接错误就查了整整一下午后来才搞明白是版本和运行库匹配的问题。这篇文章就是我沉淀下来的完整配置流程覆盖HALCON安装、环境变量、VS2013和Qt两种方式调用HALCON的配置步骤再加上实际踩过的坑。如果你在维护老产线的视觉项目或者准备在Win7上接手别人的HALCON工程这篇应该能帮你少走不少弯路。1. 环境选型先把HALCON、Qt和VS2013的版本对应关系定下来1.1 什么场景需要这种“老组合”先说说什么情况会遇到这种配置。工业现场很多已经验收的设备工控机出厂预装的就是Win7上位机界面用Qt搭建视觉部分调用HALCON算法库整个C工程又是VS2013构建的。这类项目换不了系统产线每天在跑驱动和设备SDK都绑死了旧平台开发机只能跟着项目走。还有一种更常见的情况就是公司历史代码库就是VS2013工程新同事接手时新配的电脑也必须是同一套工具链否则代码风格、编译参数全都要重新捋一遍。这个组合最大优势是稳定。HALCON 13在Win7上跑得很稳VS2013对应的MSVC编译器版本工具集v120和Qt 5.6/5.9时代是完美搭配工控机上做视觉任务性能也够。坏处是版本选择容错余地小选错一个版本编译期报错还能忍运行期弹窗找不到DLL才让人头疼。所以我一直坚持一个原则先定版本再定架构最后才动手装环境。1.2 HALCON、VS2013、Qt三者怎么匹配关于HALCON版本我推荐以HALCON 13.0为例来配置。13这个版本和VS2013的时间线非常贴近它对MSVC2013编译器和C11支持得最自然安装包里的C接口也专门考虑过Win7下的运行环境。更高版本的HALCON17之后对编译器要求越来越高VS2013编译出来的程序链接时经常会有兼容性警告所以老平台就老老实实用旧版本别追新。Qt这边要注意一个关键点VS2013对应的MSVC编译器官方预编译包只支持到Qt 5.9左右。Qt 5.10开始官方不再发布MSVC2013的预编译二进制所以如果你用Qt 5.14或者更高版本就面临两个选择要么放弃VS2013升级到VS2015/2017要么自己用VS2013编译整套Qt源码。自己编Qt源码太折腾除非公司有专门基础架构的人维护否则不推荐。我实际项目里用的是Qt 5.6.3这个版本在Win7上极其稳定而且有些老工控机连WinXP都支持兼容性很宽。所以最简单可靠的组合就是Win7 SP1 VS2013 Qt 5.6.3/5.9.xMSVC2013版本 HALCON 13。这套组合经过产线验证踩坑文档也丰富遇到问题都能找到参考。1.3 32位还是64位这里一定要想清楚决定架构这件事必须在装任何东西之前定死。通常有两种情况工控机系统是32位Win7那没得商量全套走32位Qt选MSVC2013 32bitHALCON选x86-win32。工控机是64位Win7但历史项目编译的是32位程序那么Qt和HALCON仍然选32位。很多老设备厂商SDK只有32位为了兼容只能整体32位。如果项目全新且明确使用64位那Qt选MSVC2013 64bitHALCON选x64-win64。这里必须提醒一句Qt的位数和HALCON库的位数必须一致。比如Qt工程是32位链接了64位的halconcpp.lib编译的时候可能直接报“模块计算机类型x64与目标计算机类型x86冲突”或者编译过去了运行期崩溃。这个坑我见过太多次因为VS的解决方案平台看得清清楚楚Qt Creator里Kit的ABI却很容易忽略。HALCON在安装好之后bin目录下通常有两个子目录x86-win32和x64-win64分别对应32位和64位架构。如果你的开发机是64位系统也不能两个环境变量都加HALCONARCH必须明确指定一个我一般直接写死为x64-win64或x86-win32避免HDevelop执行时找错架构。2. 安装HALCON目录结构、环境变量与许可证2.1 安装细节与目录结构HALCON安装包从官网或者供应商那边拿安装时路径尽量保持默认比如C:\Program Files\MVTec\HALCON-13.0。网上有些教程让改到D盘实际经验是没必要默认路径反而最省事因为HDevelop、示例程序、帮助文档都默认按这个路径找资源。如果一定要改路径里不要出现中文和空格后续环境变量、VS工程里写路径都会少很多麻烦。安装结束后打开HDevelop跑一个算子测试没有报错说明基础安装成功。然后你需要熟悉一下HALCON安装目录的几个关键文件夹后面配置全部靠它们bin核心DLL和HDevelop可执行文件。比如halcon.dll、halconcpp.dll分别在bin\x64-win64或bin\x86-win32下。lib导入库文件比如halconcpp.lib、halcon.lib。includeC接口头文件重点看include\halconcpp下面的HalconCpp.h。doc帮助文档和示例程序。license许可证文件存放目录。2.2 环境变量怎么设环境变量是整个配置中优先级最高的一环。HALCON安装完成后安装器一般会自动写入HALCONROOT变量但为了保险我建议你手动检查一遍并补全另外几个变量。右键“计算机” → “属性” → “高级系统设置” → “环境变量”在用户变量里确认或新增HALCONROOT指向HALCON安装目录比如C:\Program Files\MVTec\HALCON-13.0。这是HDevelop和程序查找HALCON资源的基础。HALCONARCH指定平台架构x64-win64或x86-win32。这个变量特别重要因为很多脚本和示例都是靠它拼接路径。HALCONIMAGES示例图像目录一般在安装目录的examples\images下面。设置后HDevelop里打开示例图方便不影响编译。HALCONLICENSE指向许可证文件license.dat所在路径。如果使用试用许可或者手工放置的许可文件这个变量就必须设置。另外千万不能漏掉PATH。把%HALCONROOT%\bin\%HALCONARCH%加进PATH末尾这样程序运行时才能找到halcon.dll和halconcpp.dll。CLR程序、Qt程序、VS生成的exe启动时都会按PATH顺序查找动态库没加这一步后面所有的“没有找到DLL”弹窗都从这里来。加完环境变量需要重启VS或者Qt Creator已打开的所有软件都要重启一次环境变量才会被重新读取。2.3 许可证配置与常见提示HALCON必须有许可证才能运行安装包一般会带临时的试用许可证时长14天到30天不等。正式项目基本是购买正式license供应商会给你一个license.dat文件。手动配置许可证时把这个文件放到C:\Program Files\MVTec\HALCON-13.0\license\目录下然后确保上面说的HALCONLICENSE环境变量指向这个文件。我遇到过几种许可证相关的报错程序启动时弹出“License file not found”说明HALCONLICENSE设置不对提示“License expired”大多是系统时间被改到了许可证有效期之外还有一种是“Invalid license key”基本上是license文件与HALCON版本号或者机器ID不匹配。使用正当渠道申请试用许可的话有效期到了就再去申请一个把新的license.dat替换掉原文件同时检查系统时间是否同步正常这个问题基本就解决了。需要注意不要轻信网上各种破解文件和注册机工业环境里稳定第一许可证出问题找供应商支援才是正路。3. VS2013调用HALCON包含目录、库目录和链接配置三步走3.1 创建测试工程并确认平台打开VS2013新建一个Win32控制台应用程序或者直接新建空项目都行我习惯用空项目干净。建好后首先要确认解决方案平台。默认是Win3232位如果你的HALCON是x64-win64就必须在工具栏上把平台切换为x64。如果平台列表里没有x64右键解决方案 → “配置管理器” → “活动解决方案平台” → “新建”选择x64。这里有一个非常容易踩坑的地方很多人设置了HALCON的包含目录和库目录但忘记检查当前配置是Debug还是Release以及平台是不是自己的目标平台。VS项目属性里“包含目录”“库目录”“附加依赖项”这三项Debug和Release、Win32和x64是分开存储的所以在Win32下配了切换到x64还要再配一遍。我惯用的做法是只维护Release x64或Win32的配置把调试也放到Release模式下跑这样可以少维护一半的配置项。HALCON的C库本身不区分Debug和Release版本所以用Release模式调试是行得通的。3.2 头文件和库路径配置右键项目 → “属性”打开“配置属性”。先看“VC目录”这一项“包含目录”添加两项C:\Program Files\MVTec\HALCON-13.0\includeC:\Program Files\MVTec\HALCON-13.0\include\halconcpp“库目录”添加一项C:\Program Files\MVTec\HALCON-13.0\lib\x64-win64根据你的架构选择x64-win64或x86-win32然后切到“链接器” → “输入”在“附加依赖项”里填上halconcpp.lib。这一步是把HALCON的C接口导入库链接到你生成的exe里。C接口封装了HALCON的底层C接口所以只需要链接halconcpp.lib不需要再手动加halcon.libhalconcpp.lib内部会处理好依赖关系。配置完成后在源文件顶部写一个最简的引用测试#include halconcpp/HalconCpp.h #include iostream int main() { try { HalconCpp::HImage image; image.ReadImage(C:/test.png); HalconCpp::HTuple w image.Width(); HalconCpp::HTuple h image.Height(); std::cout image size: w.I() x h.I() std::endl; } catch (HalconCpp::HError e) { std::cerr HALCON error: e.ErrorMessage().Text() std::endl; return 1; } return 0; }注意ReadImage(C:/test.png)这个路径先放一张测试图到C盘根目录确认能读取到。如果读取成功输出图片尺寸说明VS2013调用HALCON的链路已经通了。3.3 运行库与代码生成设置这部分是很多人忽略但问题最多的地方。打开“配置属性” → “C/C” → “代码生成”看“运行库”这一项。VS2013默认的Debug模式是“多线程调试DLL/MDd”Release模式是“多线程DLL/MD”这个保持默认就行。不要因为觉得“静态编译部署更省事”就改成“多线程静态库/MT”改完之后链接HALCON库时极容易出现LNK2038“RuntimeLibrary不匹配”的错误。这个错误的原因很好理解MSVC编译每个模块时CRT的运行库使用方式必须是同一套。HALCON的预编译库默认符合动态DLL的CRT链接方式你的工程若是静态CRT两边对不上编译器就会拒绝链接。一旦遇到LNK2038先把工程切回/MD或/MDd再重新编译。另外一个偶尔会遇到的问题是“C4996”这类安全警告。HALCON的老版本头文件里用了某些可能被标记为废弃的CRT函数VS2013编译时会有警告。直接把“配置属性” → “C/C” → “高级”里的“警告级别”调到“/W3”或者忽略特定警告都行不影响使用。3.4 32位和64位库路径千万别搞错我遇到过一个实际案例项目里HALCON x64环境都配好了链接器也不报错但每次运行到ReadImage就闪退。查了很久发现exe是x64的但.h文件里用了另一个同事拷贝进来的32位版halconcpp.dll在PATH里面程序启动时先找到了32位的DLL和64位exe加载不兼容。这类问题不建议靠眼睛查用Dependencies工具或者VS自带的dumpbin查看exe依赖确认分析出来的DLL路径指向哪个架构这是最快的方式。4. Qt调用HALCONKit设置、pro文件与第一个界面Demo4.1 Qt版本选择与编译套件Kit配置在Qt环境下调用HALCON首先保证你安装的Qt是MSVC2013对应的版本。我是用Qt 5.6.3的离线安装包安装时勾选msvc2013的32位或64位组件。注意别勾mingw版本HALCON的lib是MSVC编译的mingw链接不上这是新手的常见错误。安装好之后打开Qt Creator“工具” → “选项” → “构建套件Kit”。正常情况下Qt Creator能自动识别VS2013的MSVC编译器。如果没有识别手动添加编译器路径一般在这里32位编译器C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\cl.exe64位编译器C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\x86_amd64\cl.exe添加编译器时注意“ABI”设置要和你选的Qt库匹配。Qt是MSVC2013 32bitABI就选x86-windows-msvc2013-pe-32bit。如果ABI设置不对即使能编译最后生成的程序也可能因为位数不匹配运行不了。配置完Kit后新建Qt Widgets Application时直接选这个MSVC2013的Kit创建工程。4.2 pro文件里怎么配置HALCON相比VS2013的图形界面配置Qt就是在.pro文件里加路径。我把HALCON的公共部分抽出来设置一个变量后续维护方便QT core gui greaterThan(QT_MAJOR_VERSION, 4): QT widgets TARGET HalconQtDemo TEMPLATE app CONFIG c11 HALCON_ROOT C:/Program Files/MVTec/HALCON-13.0 INCLUDEPATH $$HALCON_ROOT/include \ $$HALCON_ROOT/include/halconcpp LIBS $$HALCON_ROOT/lib/x64-win64/halconcpp.lib SOURCES main.cpp mainwindow.cpp HEADERS mainwindow.h FORMS mainwindow.ui这里有几个细节LIBS $$HALCON_ROOT/lib/x64-win64/halconcpp.lib这种写法直接给全路径并带上双引号比-L和-l的组合更容易避免路径空格导致的解析问题。HALCON_ROOT两边的双引号在qmake里可以作为字符串值的一部分拼接时也不会因为路径里有空格而断掉。如果你的HALCON是x86-win32把lib路径改成对应目录即可。如果你同时维护多个机器不同机器HALCON安装路径可能不同把HALCON_ROOT这一行抽出来标注清楚换机器只改这一行就行。4.3 在Qt界面里调用HALCON算子界面设计很简单一个按钮、一个QLabel显示原图、一个QLabel显示处理结果。为了不让Qt的moc机制处理含HALCON头文件的头文件我在mainwindow.h里不引入任何HALCON头文件只在mainwindow.cpp里包含halconcpp/HalconCpp.h。这个小习惯能避免很多莫名其妙的moc编译错误。按钮的槽函数代码如下#include mainwindow.h #include ui_mainwindow.h #include halconcpp/HalconCpp.h #include QFileDialog #include QDebug QImage HImageToGrayQImage(HalconCpp::HImage image) { HalconCpp::Hlong pointer 0; HalconCpp::HTuple type; HalconCpp::Hlong width 0, height 0; image.GetImagePointer1(pointer, type, width, height); QImage qimg((const uchar*)pointer, (int)width, (int)height, (int)width, QImage::Format_Grayscale8); return qimg.copy(); } MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui-setupUi(this); connect(ui-btnOpen, QPushButton::clicked, this, MainWindow::onOpenImage); } MainWindow::~MainWindow() { delete ui; } void MainWindow::onOpenImage() { QString path QFileDialog::getOpenFileName(this, 选择图片, , Images (*.png *.jpg *.bmp)); if (path.isEmpty()) return; try { HalconCpp::HImage image; image.ReadImage(path.toLocal8Bit().constData()); HalconCpp::HImage gray image.ConvertImageType(gray); HalconCpp::HRegion region gray.Threshold(0.0, 128.0); HalconCpp::HTuple area, row, column; region.AreaCenter(area, row, column); ui-lblResult-setText( QString(面积: %1\n中心: (%2, %3)) .arg((long long)area[0].L()) .arg((double)row[0].D()) .arg((double)column[0].D())); QImage qimg HImageToGrayQImage(gray); ui-lblImage-setPixmap(QPixmap::fromImage(qimg)); } catch (HalconCpp::HError err) { qDebug() HALCON error: err.ErrorMessage().Text(); } }这里的最关键点是path.toLocal8Bit().constData()。在Win7中文环境下Qt的QString默认是UTF-16传给HALCON的ReadImage时如果直接转UTF-8HALCON底层用ANSI读取文件中文路径大概率乱码。用toLocal8Bit()转成系统本地代码页读中文路径图片就正常了。如果你的图片路径里有中文用这个技巧如果全是英文路径转成toStdString()也可以。4.4 HImage转QImage时为什么必须copy代码里HImageToGrayQImage这个函数最后一句写的是return qimg.copy()这个copy()非常重要。HALCON的HImage对象内部管理图像内存函数返回后image对象可能析构也可能在后续算子调用中改变内部存储。QImage如果不copy只是浅拷贝数据指针图片数据随时会被释放界面上就会出现“花屏”或者随机崩溃。我早期犯过这个错固定复现的流程是第一次显示正常第二次再点按钮就崩溃查了好几个小时才定位到QImage的浅拷贝问题。如果你的图像是彩色图HALCON的GetImagePointer3返回三个独立的通道指针构造QImage时需要用这三个通道合并成一个RGB32的QImage或者用HALCON的InterleaveChannels算子先把通道交织成RGB图像再通过GetImagePointer转出来。工业项目里通常先转灰度再处理所以我这个示例就按灰度图处理逻辑简单也够用。5. 运行时部署从开发机到工控机的最后一公里5.1 程序跑不起来时先查DLL很多环境配置在开发机上跑得很欢把exe拷到干净工控机上就弹“无法启动此程序因为计算机中丢失halconcpp.dll”。别慌这就是运行时依赖没带上。最直接的解决办法有两个第一把HALCON的bin\x64-win64目录下的halcon.dll、halconcpp.dll复制到exe同级目录第二在工控机上重新安装一次HALCON Runtime或者完整版HALCON并把bin目录加入PATH。第一种方式更常用因为现场往往不允许随便装软件拷贝DLL最干净。另外还要注意VS2013的运行库。如果你的程序是用VS2013编译的目标工控机上必须安装对应的VC运行库否则会提示丢失MSVCP120.dll或MSVCR120.dll。开发机上能跑是因为VS安装时已带运行库裸工控机没有。把VS2013安装目录下或者微软官网下载的vcredist_x86.exe和vcredist_x64.exe都装上两种位宽都装因为HALCON本身可能依赖32位运行库你的主程序可能是64位的一个都不能缺。5.2 许可证的部署与备份现场部署时许可证文件是不能忘记的。把license.dat文件放到程序同级的license目录或者HALCON许可目录然后在程序启动代码里显式设置环境变量qputenv(HALCONLICENSE, C:/MyApp/license/license.dat); qputenv(HALCONROOT, C:/Program Files/MVTec/HALCON-13.0);在QApplication创建之前调用qputenv可以保证HALCON在初始化时读到正确的配置。这样做的好处是不依赖系统的全局环境变量换机器部署时不用手动改系统配置。我遇到过现场机器时间被重置导致HALCON许可证突然失效的问题。后来在部署文档里专门写了一条工业现场的工控机尽量使用NTP时间同步或者每次维护时检查系统时间。这个细节看起来和技术无关但关键时刻能省一大笔现场出差成本。6. 常见问题排查把我在Win7上踩过的坑整理成表6.1 问题速查表下面这些问题是Win7 VS2013 Qt HALCON组合下最高频的报错我直接整理成表格现象原因解决办法提示找不到halconcpp.dllPATH没配好或DLL不在exe目录把HALCON的bin目录加入PATH或将halcon.dll、halconcpp.dll复制到exe同级目录链接报LNK2019无法解析的外部符号没有链接halconcpp.lib或库路径位数不对检查“链接器—输入—附加依赖项”确认HALCON库路径是x64-win64还是x86-win32编译报LNK2038 RuntimeLibrary不匹配工程用了静态CRT与HALCON的动态CRT不一致统一使用/MD或/MDd不要用/MT提示MSVCP120.dll丢失目标机没装VS2013运行库安装vcredist_x86.exe和vcredist_x64.exeQt Creator提示“Qt没有被正确安装请运行make install”Kit里编译器选错或ABI不匹配重新选择MSVC2013编译器ABI设为对应的x86或x64格式程序能编译但点按钮就闪退可能是图像内存浅拷贝也可能是DLL位数不一致QImage必须copy()检查exe实际加载的HALCON DLL位数中文路径图片读取失败Qt字符串编码与HALCON ANSI读取方式不一致用path.toLocal8Bit().constData()传路径HALCON许可证过期或找不到license.dat路径错误、系统时间不对、许可文件失效检查HALCONLICENSE变量替换有效license.dat同步系统时间include halconcpp/HalconCpp.h时报错包含目录没加include和include/halconcpp按文中步骤把两个include目录都加上6.2 几个我后来形成的“固定操作”经历这些坑之后我总结了一套固定操作每当在VS2013和Qt之间切换项目时先把环境变量检查一遍特别是PATH里是不是残留了别的版本HALCON的bin目录。多版本HALCON共存是环境问题的最主要来源我见过有人机器上装了HALCON 13和HALCON 20PATH里两个bin目录都存在HDevelop还是旧版本但程序链接的是新库最后行为完全不可控。建议一台开发机只保留一个HALCON版本或者至少把PATH里的旧版本bin目录删干净需要测试旧版本时再用脚本切换环境变量。另一个固定操作是写配置脚本。我在项目根目录放一个set_halcon_env.bat内容就是设置HALCONROOT、HALCONARCH、HALCONLICENSE这几个变量然后用这个批处理启动VS和Qt Creator。这样不管谁接手电脑只要先运行这个脚本环境就不会错。6.3 还有两个冷门但致命的问题继续说两个比较偏的问题。第一个是VS2013在Win7上编译时偶尔报“TRK0005: Failed to locate: cl.exe”这不是HALCON的问题而是VS的“VC目录”路径配置损坏在“工具—选项—项目和解决方案—VC目录”里恢复默认值或者重装VS组件就能解决。第二个是Qt Creator在Win7上打开HALCON相关工程时如果你在头文件里包含HalconCpp.hmoc处理时会偶发“class HalconCpp has no member”这类误报。本质上moc只是扫描带Q_OBJECT的头文件HalconCpp.h里存在大量模板和宏偶尔会干扰moc解析。解决办法就是我前面说过的不在头文件里include HalconCpp.h只在.cpp文件里include。如果必须放在头文件给这个类关闭moc处理或者改用Q_DECLARE_OPERATORS_FOR_FLAGS这类隔离方式不过最省心的还是.cpp隔离。结尾关于这套环境我最后想说几句这套环境配置看起来是给“老古董”准备的但工业项目里它就是最可靠的选择。我后来配环境已经形成模板了先锁版本、再定架构、然后配置环境变量、最后在VS2013和Qt里各跑一次读图Demo。整个过程从拆箱到跑通Demo基本控制在半小时以内。个人体会是这类老平台配置最怕“差不多”三个字版本差一位、位宽错一个、运行库混一套后面排查成本都是成倍的。如果你照着文档配完还是有问题建议重新检查一下PATH里每个DLL的实际位宽还有license文件是否真的能读到。环境配置顺利了后面写视觉算法的时间才不会被无谓的编译错误吃掉太多。
返回列表