存档在 ‘QT’ 分类

Linux下OpenCv+Qt搭配使用问题

2016年5月4日

发现一个奇怪的现象,OpenCv代码在直接使用g++或者cmake+make编译后代码能正常跑出效果,但是以Qt组织工程后,任何涉及到OpenCv的代码都导致程序崩溃,比如segment error(段错误),relloc error或者the inferior has stopped because receive a signal的错误,经过多次实验排查,定位到问题。

现象:
使用原生的g++编译没问题

g++  -ggdb `pkg-config --cflags opencv` main.cpp -o main `pkg-config --libs opencv`  

使用Cmake没问题,CMakeLists.txt内容如下:

######## A simple cmakelists.txt file for OpenCV() #############
cmake_minimum_required(VERSION 2.8)
PROJECT(ShowImage)
FIND_PACKAGE( OpenCV REQUIRED )   
INCLUDE_DIRECTORIES( 
  ${ShowImage_SOURCE_DIR}
)
ADD_EXECUTABLE(ShowImage main.cpp)  
TARGET_LINK_LIBRARIES (ShowImage ${OpenCV_LIBS} )
cmake .
make

在QtCreator中,配置文件中加有

INCLUDEPATH+=/usr/local/include\
/usr/local/include/opencv\
/usr/local/include/opencv2
LIBS+=/usr/local/lib/libopencv_highgui.so\
/usr/local/lib/libopencv_core.so\
/usr/local/lib/libopencv_imgproc.so\
/usr/local/lib/libopencv_imgcodecs.so \
/usr/local/lib/libopencv_superres.so \
/usr/local/lib/libopencv_videoio.so \
/usr/local/lib/libopencv_calib3d.so \
/usr/local/lib/libopencv_video.so \
/usr/local/lib/libopencv_features2d.so \
/usr/local/lib/libopencv_videostab.so \
/usr/local/lib/libopencv_flann.so \
/usr/local/lib/libopencv_highgui.so \
/usr/local/lib/libopencv_imgcodecs.so \
/usr/local/lib/libopencv_imgproc.so \
/usr/local/lib/libopencv_ml.so \
/usr/local/lib/libopencv_objdetect.so 

但是程序总是停止运行。

解决办法:
首先

qmake -v
QMake version 2.01a
Using Qt version 4.8.6 in /usr/lib/x86_64-linux-gnu

可以看出当前该系统安装的Qt版本。在编译OpenCv时带的参数WITH_QT=ON选项会导致OpenCv编译时使用qt4,应该是这种关联导致冲突或者不匹配。
你现在可以这样做:

cd build
make uninstall
make clean
cd ..
rm -rf build

即卸载,清除,删除文件夹,现在只需要将opencv重新编译一遍即可,注意去掉WITH_QT=ON选项。

ubuntu下opencv2.4.9/3.0/3.1安装过程

2016年5月3日

安装OpenCv后出现各种问题,究其原因是一些基础库没有安装好,以下是基础库安装步骤,保证尽量完整,免得在使用的时候出错。

  • 1.由于opencv的cmakelist里依赖一些库,所有要先配置好这些库,先去除你电脑上的这些重新装.
  •  apt-get remove ffmpeg x264 libx264-dev
  • 2.安装其他依赖库.
  •  apt-get update
     apt-get install build-essential checkinstall Git cmake libfaac-dev libjack-jackd2-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libsdl1.2-dev libtheora-dev libva-dev libvdpau-dev libvorbis-dev libx11-dev libxfixes-dev libxvidcore-dev texi2html yasm zlib1g-dev
  • 3.安装gstreamer,主要是opencv里头的相机模块用到
  •   apt-get install libgstreamer0.10-0 libgstreamer0.10-dev gstreamer0.10-tools gstreamer0.10-plugins-base libgstreamer-plugins-base0.10-dev gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly gstreamer0.10-plugins-bad gstreamer0.10-ffmpeg

    如果 gstreamer0.10-ffmpeg提示没有候选,那么手动下载并安装,或者按如下步骤安装

     apt-get install libgstreamer0.10-dev gstreamer-tools gstreamer0.10-tools gstreamer0.10-doc
    apt-get install gstreamer0.10-plugins-base gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly gstreamer0.10-plugins-bad gstreamer0.10-plugins-bad-multiverse  

    所有您需要做的就是添加PPA到您的系统,更新本地存储索引和安装gstreamero.10-ffmpeg包。如下输入命令:

     add-apt-repository ppa:mc3man/trusty-media
    apt-get update
    apt-get install gstreamer0.10-ffmpeg
  • 4.安装gtk,jpeg8
  •  apt-get install libgtk2.0-0 libgtk2.0-dev
    apt-get install libjpeg8 libjpeg8-dev
  • 5.安装 install x264.
  • 下载链接: ftp://ftp.videolan.org/pub/videolan/x264/snapshots

     tar xvf x264-snapshot-**********-stable.tar.bz2
    cd x264-snapshot--**********--stable
    ./configure --enable-shared --enable-pic
    make
     make install

    由于我的电脑是64位,所以要加上 –enable-shared –enable-pic ,否则就会报错:

        /usr/bin/ld: /usr/local/lib/libavcodec.a(avpacket.o): relocation R_X86_64_32S against `av_destruct_packet' can not be used when making a shared object; recompile with -fPIC
        /usr/local/lib/libavcodec.a: could not read symbols: Bad value
  • 6.安装ffmpeg
  • 如果出现下面错误:

     /usr/local/lib/libswscale.a(swscale_unscaled.o): relocation R_X86_64_32S against `av_pix_fmt_descriptors@@LIBAVUTIL_52' can not be used when making a shared object; recompile with -fPIC
    /usr/local/lib/libswscale.a: error adding symbols: 错误的值
    collect2: error: ld returned 1 exit status
    make[2]: *** [lib/libopencv_highgui.so.2.4.9] 错误 1
    make[1]: *** [modules/highgui/CMakeFiles/opencv_highgui.dir/all] 错误 2
    make: *** [all] 错误 2

    可能是opencv249依赖的ffmpeg版本不对照

     wget http://ffmpeg.org/releases/ffmpeg-1.2.tar.bz2
    tar xvf ffmpeg-1.2.tar.bz2
    cd ffmpeg-1.2
    ./configure --enable-gpl --enable-libfaac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --enable-nonfree --enable-postproc --enable-version3 --enable-x11grab --enable-shared --enable-pic
    make
    make install
  • 7.安装v4l (video for linux) , http://www.linuxtv.org/downloads/v4l-utils/.
  • 报错:dvb-v5.h:69:9: error: ‘NULL’ undeclared here ……..原因是v4l的版本不对,于是我装了v4l 1.0.0

     wget http://www.linuxtv.org/downloads/v4l-utils/v4l-utils-1.0.0.tar.bz2
    tar xvf v4l-utils-1.0.0.tar.bz2
    cd v4l-utils1.0.0
    make
    make install
  • 8.安装OpenCV 2.4.9.
  •  tar xvf OpenCV-2.4.9.tar.bz2
    cd OpenCV-2.4.9/
    mkdir build
    cd build
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_V4L=ON  -D WITH_OPENGL=ON ..
    make
    make install

    -D WITH_QT=ON选项就别加上了,免得在Qt中用不了
    环境变量中添加

     export LD_LIBRARY_PATH=/usr/local/lib

    另外修改

     sudo vi /etc/ld.so.conf.d/opencv.conf

    追加 /usr/local/lib
    执行

     sudo ldconfig /etc/ld.so.conf

    在/etc/bash.bashrc添加

     PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
    export PKG_CONFIG_PATH

    最后查看版本和头文件目录

     pkg-config --modversion opencv
    pkg-config --cflags opencv 

如果准备在Qt Creator中写代码,关注下一篇文章:Linux下OpenCv+Qt搭配使用问题

Qt中将TableView里的数据导出到Excel

2015年12月15日

Qt中将TableView里的数据导出到Excel的解决方案网络上不太多,我这里综合各路资源,给大家提供参考。
将Excel文件当成是一个数据库
使用MS的ODBC或ADO都可以将Excel文件当做一个数据库,那么我们只需要使用下面这个DSN连接串去创建并连接至该Excel文件:

QString dsn = QString("DRIVER={Microsoft Excel Driver (*.xls)};DSN=''; FIRSTROWHASNAMES=1;;CREATE_DB=/"%1/";DBQ=%2").

                  arg(excelFilePath).arg(excelFilePath);

2. 将Excel的工作表(sheet)当成是一个数据库表
可以使用SQL语句“CREATE TABLE” 去创建一个工作表。
3. 向表中插入数据
使用SQL的“INSERT”语句插入数据。
4. Unicode支持
是的,列名和数据都支持Unicode。
先看看图片,再直接提供代码,代码很简单,一看便懂。
QQ图片201512151313182
代码下载链接:

  Excel.rar (6.1 MiB, 343 hits)

Qt中异常定位

2015年1月4日

以前记录过C#开发应用程序时程序异常崩溃时的调试记录程序,链接为:C#开发的应用程序:自动退出原因查找

在Qt中首先需要在头文件中包含“#include
SetUnhandledExceptionFilter函数是Win32API的异常捕获函数,在程序异常结束前,会调用该函数注册的回调函数,这样就能在进程终止前执行指定的代码,达到例如保存数据的功能。

LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//异常捕获
    /*
      ***保存数据代码***
    */
    //这里弹出一个错误对话框并退出程序
    EXCEPTION_RECORD* record = pException->ExceptionRecord;
    QString errCode(QString::number(record->ExceptionCode,16)),errAdr(QString::number((uint)record->ExceptionAddress,16)),errMod;
    QMessageBox::critical(NULL,"崩溃","<FONT size=4><div><b>程序发生崩溃</b><br/></div>"+
        QString("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
        QMessageBox::Ok);
    return EXCEPTION_EXECUTE_HANDLER;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);//注册异常捕获函数
    MainWindow w;
    w.showMaximized();
    return a.exec();
}

保存数据仅是挽救措施,更重要的是找到错误的根源。若能在崩溃的同时,程式自动记录下崩溃时的运行信息,将有助于修正工作。微软提供了“DbgHelp”错误调试技术,调用相关功能即可保存程式崩溃时的信息,然后借助WinDbg软件就能分析出当时的执行状况。

使用它需要链接“DbgHelp”库,调用MiniDumpWriteDump函数保存以“.dmp”为后缀的Dump文件,该文件能被WinDbg读取并分析。

LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException){//程式异常捕获
    /*
      ***保存数据代码***
    */
    //创建 Dump 文件
    HANDLE hDumpFile = CreateFile(QTime::currentTime().toString("HH时mm分ss秒zzz.dmp").utf16(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if( hDumpFile != INVALID_HANDLE_VALUE){
        //Dump信息
        MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
        dumpInfo.ExceptionPointers = pException;
        dumpInfo.ThreadId = GetCurrentThreadId();
        dumpInfo.ClientPointers = TRUE;
        //写入Dump文件内容
        MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
    }
    //这里弹出一个错误对话框并退出程序
    EXCEPTION_RECORD* record = pException->ExceptionRecord;
    QString errCode(QString::number(record->ExceptionCode,16)),errAdr(QString::number((uint)record->ExceptionAddress,16)),errMod;
    QMessageBox::critical(NULL,"崩溃","<FONT size=4><div><b>程序发生崩溃</b><br/></div>"+
        QString("<div>错误代码:%1</div><div>错误地址:%2</div></FONT>").arg(errCode).arg(errAdr),
        QMessageBox::Ok);
    return EXCEPTION_EXECUTE_HANDLER;
}

当被错误困扰得焦头烂额的时候,能直接告诉错误在哪一行代码该有多好呀!事实上WinDbg就能做到。
在项目的pro工程文件中加入:QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /DEBUG
这句话的目的是Release版也将生成“.pdb”后缀的调试信息文件。在使用WinDbg导入Dump前,指定好源码与pdb文件的位置,即可在错误报告内看到罪魁祸首是哪一行代码。

VS与Qt Creator中使用Qwt配置

2014年7月26日

很早以前就使用过Qwt这个开源库,也分别在VS中与Qt Creator中使用,两种编辑器配置方法不尽相同,这里做个区分。

  • #1 VS2012中配置

  • 分别在vs2012项目配置中添加如下选项:
    (1)属性->配置属性->C/C++->常规,附加包含目录:$(QTDIR)\include\QWT(甚至可以直接将qwt目录拷贝到Qt的msvc2012目录中。)
    (2)属性->配置属性->链接器->输入,附加依赖项:qwtd.lib
    (3)属性->配置属性->C/C++->预处理器,预处理器定义:QWT_DLL

  • #2 Qt Creator中配置

  • 分别在pro文件中添加如下代码:
    (1)LIBS += -L”D:\Qt\Qt5.2.1\5.2.1\msvc2012\lib”
    (2)LIBS += -lqwt
    (3)CONFIG += qwt
    (4)DEFINES += QWT_DLL

QString::fromWCharArray链接出错解决办法

2014年7月14日

在使用如下代码时:

QString::fromWCharArray(L"姓名")

vs2012 提示如下错误:

error LNK2019: unresolved external symbol "__declspec(dllimport)
public: static class QString __cdecl QString::fromWCharArray(wchar_t const *,int)"
(__imp_?fromWCharArray@QString@@SA?AV1@PB_WH@Z) referenced in function "public:
void __thiscall midiIO::queryMidiInDevices(void)" (?queryMidiInDevices@midiIO@@QAEXXZ)

解决办法为:项目(Project) –> 属性(Properties) –> 配置属性(Configuration Properties) –>C/C++ –>(语言)Language,设置将“Wchar_t视为内置类型”设置为“是(/Zcwchar_t)”

BUG报告:线程死锁

2014年5月15日

一段帧的完整性匹配算法,有线程死锁的情况,在该文的第23行的continue应为break;

原因分析:
当循环队列中数据个数少于2时,消费者线程一直执行if(cir.size() < 2) continue,在执行的同时还占有锁;在生产者端有数据要放入循环队列时,试图获得互斥锁失败,导致数据插入循环队列失败。最终的结果是消费者线程一直饥饿等待数据到来,生产者有很多数据但是不能获得锁而不能产生数据。

Qt中使用中文注释产生的奇异问题

2014年5月15日

在使用Qt编写一个状态指示灯时,定义了类中嵌套的结构体,使用了如下的代码:

struct HLed::Private
{
public:
    enum LightState{ON, OFF, ERR};
    Private(): color(Qt::green), lightState(ON){}
    //灯的颜色
    QColor color;
    //灯的状态
    LightState lightState;
};

编译提示以下错误:

error: C2614: “HLed::Private”: 非法的成员初始化:“lightState”不是基或成员

对于一个以C++作为母语的人来说,我确实不能发现哪里有问题。在我重敲代码后,奇迹般的错误没有了,对比前后的异同,发现是注释引起,修改成这样就行了

struct HLed::Private
{
public:
    enum LightState{ON, OFF, ERR};
    Private(): color(Qt::green), lightState(ON){}
    QColor color;
    LightState lightState;
};

结论:Qt对中文的兼容性还不太好,在程序中使用中文时,当字数为奇数时会出现乱码,不得不将字数凑偶,有时候甚至偶数个字数也会出现错误。