Qt+OpenCV通用视觉框架全套源码。 Qt+OpenCV通用视觉框架全套源码。 工具可扩展。 除了opencv和相机sdk的dll,其它所有算法均无封装,可以根据自己需要补充自己的工具。 基于 Qt5.12.12 + VS2019 + OpenCV 开发实现,支持多相机多线程,每个工具都是单独的 DLL,主程序通过公用的接口访问以及加载各个工具。 包含涉及图像算法的工具、 逻辑工具、通讯工具和系统工具等工具

搞视觉开发最头疼的就是框架扩展性,今天给大伙儿扒一套我用了三年的Qt+OpenCV通用框架。这玩意儿最骚的是除了相机驱动和OpenCV核心库,所有算法模块都跟乐高似的随便插拔——想换哪块换哪块,老板再也不用担心我通宵改架构了。

先看这个相机管理模块怎么玩多线程。每个相机实例单独开线程跑,通过Qt的信号槽机制把图像数据甩给处理模块,根本不用担心UI卡死。看这段相机初始化代码:

// 相机工厂类创建实例
CameraBase* camera = CameraFactory::createCamera("Basler");
connect(camera, &CameraBase::frameReceived, 
        [](cv::Mat frame){ /* 处理帧数据 */ });

// 线程池管理
QThreadPool::globalInstance()->start(camera);

这里用工厂模式生成不同品牌相机的实例,QThreadPool自动管理线程生命周期。重点是这个CameraBase抽象类,所有相机SDK都要继承实现它的grabFrame()和stopGrab()方法。

说到模块扩展,框架的DLL设计才是精髓。每个工具都是独立DLL,主程序通过统一接口加载。来看图像处理工具的接口定义:

// 工具接口基类
class AlgorithmDLLInterface {
public:
    virtual QString name() const = 0;
    virtual cv::Mat process(const cv::Mat& input) = 0;
    virtual QWidget* getControlPanel() = 0;
};

// 导出函数约定
extern "C" ALGORITHM_EXPORT AlgorithmDLLInterface* createTool();

重点是这个跨DLL的接口设计,用纯虚类做契约。导出的createTool函数让主程序能动态加载工具实例。自己加新算法?新建DLL实现这三个方法就完事了。

通讯模块的设计更有意思,基于状态机的消息分发:

// 通讯管理器维护设备状态
class CommunicationManager : public QObject {
    QMap<QString, DeviceState> deviceStates;
    
public slots:
    void handleDeviceMessage(const QString& msg) {
        // 解析消息并更新对应设备状态
        emit stateChanged(parseState(msg));
    }
};

这里用QMap维护多个设备的状态,通过Qt的元对象系统实现跨线程消息处理。配合QSerialPort或TCP套接字,轻松扩展各种工业协议。

Qt+OpenCV通用视觉框架全套源码。 Qt+OpenCV通用视觉框架全套源码。 工具可扩展。 除了opencv和相机sdk的dll,其它所有算法均无封装,可以根据自己需要补充自己的工具。 基于 Qt5.12.12 + VS2019 + OpenCV 开发实现,支持多相机多线程,每个工具都是单独的 DLL,主程序通过公用的接口访问以及加载各个工具。 包含涉及图像算法的工具、 逻辑工具、通讯工具和系统工具等工具

实战中遇到过最坑的问题是多相机时间同步。后来在图像采集线程里加了硬件触发同步机制:

void AcquisitionThread::run() {
    while(!isInterruptionRequested()) {
        if(triggerSignal.wait(100)) { // 等待硬件触发信号
            cv::Mat frame = camera->grabFrame();
            emit frameGrabbed(frame);
        }
    }
}

这个triggerSignal是跨线程的QWaitCondition,配合硬件触发线路实现微秒级同步精度。注意这里用isInterruptionRequested()安全终止线程,比直接terminate()优雅多了。

环境配置千万别踩坑!记得把OpenCV的world模块编译进去,能省一堆dll依赖问题。CMake里加上这两句:

set(OpenCV_STATIC ON)
find_package(OpenCV COMPONENTS core imgproc highgui REQUIRED)

实测VS2019+Qt5.12.12组合最稳,碰到界面卡顿试试在pro文件加:QMAKECXXFLAGS += /Zc:_cplusplus

这框架最大的优点是留白足够多——算法实现全是空架子,就等着你自己填充核心逻辑。比如图像处理工具里有个骨架代码:

cv::Mat MyFilterTool::process(const cv::Mat& input) {
    cv::Mat output;
    // 这里写你的算法
    // 比如 cv::Canny(input, output, 100, 200);
    return output;
}

想加深度学习?把onnx模型往这塞就行。实测过用NCNN替换OpenCV后端,帧率能提升30%左右。

最后说下调试技巧:在VS里设置环境变量PATH包含所有依赖dll的路径,用qDebug()输出时记得加QT_MESSAGELOGCONTEXT环境变量,能显示具体代码位置。碰到DLL加载失败,用Dependency Walker查依赖链准没错。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐