Back to blog
3 min read
在Windows Embedded CE下编译OpenCV 1.10

本文讲述了编译可用于 Windows CE(同样适用于最新版本 Windows Embedded Compact 7)的 OpenCV 图像处理库。使用 OpenCV 版本为 1.10。我所移植的库有 cv 和 cxcore。由于 Highgui 和操作系统结合太紧密,我删除了大量代码,只移植了项目需要的 cvLoadImage 等几个函数。

准备工作

下载 OpenCV 1.10 版本,打开 VS 工程。建立空的 Windows CE 动态链接库 solution(静态库也是可以的),将 cv 和 cxcore 的代码添加分别加入不同的 project 。设定头文件位置和 SDK 等。 针对 WIN32 和 ARM 平台,需要设定不同的 preprocessor definitions, _UNICODEARMWIN32 等指令请参考其他工程进行设置,需要额外添加的有 CVAPI_EXPORTS, CV_DLLCXCORE_EXPORTS

修改代码

由于我的开发平台是 X86,接下来的修改都是针对此平台。 首先编译 cxcore,打开 cxerror.cpp,修改以下内容:

第 94 行(注意,行数不一定准确):

#if defined WIN32 || defined WIN64 //Changed
    #define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
        static DWORD g_TlsIndex = TLS_OUT_OF_INDEXES;
#else
    static pthread_key_t g_TlsIndex;
#endif

第 114 行:

if( g_TlsIndex == TLS_OUT_OF_INDEXES )
    //Changed
    //FatalAppExit( 0, "Only set CV_DLL for DLL usage" );
    MessageBox(0, L"Only set CV_DLL for DLL usage", L"OpenCV", MB_ICONERROR);

第 121 行:

if( !context )
{
    context = icvCreateContext();
    if( !context )
        //Changed
        //FatalAppExit( 0, "OpenCV. Problem to allocate memory for TLS OpenCV context." );
        MessageBox(0, L"OpenCV. Problem to allocate memory for TLS OpenCV context.", L"OpenCV", MB_ICONERROR);

    TlsSetValue( g_TlsIndex, context );
}

第 191 行:

//Changed
//wsprintf( message, "%s (%s)\nin function %s, %s(%d)\n\n"
sprintf( message, "%s (%s)\nin function %s, %s(%d)\n\n"
    "Press \"Abort\" to terminate application.\n"
    "Press \"Retry\" to debug (if the app is running under debugger).\n"
    "Press \"Ignore\" to continue (this is not safe).\n",
    cvErrorStr(code), err_msg ? err_msg : "no description",
    func_name, file, line );

//wsprintf( title, "OpenCV GUI Error Handler" );
//Changed
sprintf( title, "OpenCV GUI Error Handler" );

//int answer = MessageBox( NULL, message, title, MB_ICONERROR|MB_ABORTRETRYIGNORE|MB_SYSTEMMODAL );
//Changed
//int answer = MessageBox( NULL, message, title, MB_ICONERROR|MB_ABORTRETRYIGNORE );
WCHAR wmsg[2048];
MultiByteToWideChar(CP_ACP,0,title,strlen(message),wmsg,2048);
int answerr = MessageBox( NULL, wmsg, L"OpenCV GUI Error Handler", MB_ICONERROR|MB_ABORTRETRYIGNORE);

第 393 行:

#if defined WIN32 || defined WIN64
//Changed
//BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
BOOL WINAPI DllMain( HANDLE, DWORD fdwReason, LPVOID )

接下来是对 cxswitcher.cpp 的修改。

第 138 行:

//Changed
//if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0\\",
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0\\",
    0, KEY_QUERY_VALUE, &key ) >= 0 )
{
    //if( RegQueryValueEx( key, "~MHz", 0, 0, (uchar*)&val, &sz ) >= 0 )
    if( RegQueryValueEx( key, L"~MHz", 0, 0, (uchar*)&val, &sz ) >= 0 )
        cpu_info->frequency = (double)val;
    RegCloseKey( key );
}
#ifdef MASM_INLINE_ASSEMBLY
//#ifdef MASM_INLINE_ASSEMBLY && !defined ARM

第 440 行:

//Changed
//addr = (uchar*)GetProcAddress( plugins[idx].handle, name );
wchar_t tmp[1024];
swprintf(tmp, L"%s", name);
addr = (uchar*)GetProcAddress( plugins[idx].handle, tmp);

第 614 行:

//Changed
//plugins[i].handle = LoadLibrary( plugins[i].name );
wchar_t tmp[1024];
swprintf(tmp, L"%s", plugins[i].name);
plugins[i].handle = LoadLibrary( tmp );

针对 ARM,还需要修改几个地方:

第 744 行:

//#ifdef MASM_INLINE_ASSEMBLY
#ifdef MASM_INLINE_ASSEMBLY && !defined ARM

cxtypes.h 第 210 行:

#elif defined WIN32 && !defined WIN64 && defined \_MSC_VER && !defined ARM

到此应该可以正常编译 cxcore 了,如果编译时出现错误,请按照以上方式修改出错位置的预编译指令或者字符串类型等。

接下来是 cv ,由于 cv 依赖 cxcore ,需要将之前编译的 cxcore.lib 加入 cv 工程的链接目录。 cv 几乎不需要修改,但 kdtree 部分编译不过,因为我不需要使用这部分的函数,所以我删除了 kdtree 的两个文件。接下来修改 preprocessor definitions,完成编译。

Highgui 和 Windows 相关度太高,我删除了大量代码,只留下了 cvLoadImage 等几个函数。OpenCV 自带 bmp 解码,jpeg 和 png 解码需要相应的解码库。移植这些库后,将产生的 lib 文件加入 highgui 的链接目录,根据出错信息逐步修改代码,即可完成编译。