如何将OpenCV与Unicode版本的Delphi一起使用?

时间:2011-10-28 07:01:53

标签: delphi unicode opencv

我正在编辑一个名为Opencv for Delphi的开源项目,可以使用Delphi 6,Delphi 2009和Delphi xe2进行编译。

我刚刚为Delphi 6编译删除了不兼容的(例如:Application.MainFormOnTaskbar := True;)。

在运行时d6应用程序正常运行没有错误,但其余的编译得很好,但在调用cvopencv.dll时出现运行时错误。

原始项目是一个用Delphi 2007编译的西班牙项目,工作正常。

在d6 exe中我读不出任何东西,除了???????但其他人用西班牙语显示这意味着它是一个UNICODE问题,当调用cvopencv.dll时会发生错误。

如何才能使这个项目与Delphi 2009或更高版本一起工作(仍然是d2009编译好)

========================= David Heffemans回答================== ===

procedure TForm1.Button2Click(Sender: TObject);
var

   file1 : PAnsiChar; // "haarcascade_frontalface_alt.xml";
   file2 : PAnsiChar; //"haarcascade_eye.xml";
   file3 : PAnsiChar; //"haarcascade_upperbody.xml";
   SourceFileName : AnsiString;
   StorageType : Integer;
   ImSize : CvSize;

begin
   memo1.Lines.Clear;
   GetMem(Storage, SizeOf(CvMemStorage));
   SourceFileName:=Edit1.Text;
   StorageType:=0;
   storage:=nil;
   storage :=cvCreateMemStorage(storageType);
   file1 := PAnsiChar(ExtractFilePath(Application.ExeName)+'haarcascade_frontalface_alt.xml');
   file2 := PAnsiChar(ExtractFilePath(Application.ExeName)+'haarcascade_eye.xml');
   file3 := PAnsiChar(ExtractFilePath(Application.ExeName)+'haarcascade_upperbody.xml');

   cascade_f := cvLoad(file1, nil, nil, nil);
   cascade_e := cvLoad(file2, nil, nil, nil);
   cascade_ub := cvLoad(file3, nil, nil, nil);

   if cascade_f=nil then ShowMessage('Íå ìîãó çàãðóçèòü êàñêàä Face');
   if cascade_e=nil then ShowMessage('Íå ìîãó çàãðóçèòü êàñêàä Eye');
   if cascade_ub=nil then ShowMessage('Íå ìîãó çàãðóçèòü êàñêàä UpperBody');

   img := cvLoadImage(PAnsiChar(AnsiString(SourceFileName)), 1);

   cvNamedWindow((PAnsiChar(AnsiString(Edit1.Text))), 1);

   detectEyes(img);
   cvShowImage(PAnsiChar(AnsiString(SourceFileName)), img);

end;

end.

2 个答案:

答案 0 :(得分:7)

您引用的OpenCV库在标题的顶部说明了这一点:

  

用于英特尔开源计算机视觉库的Borland Delphi 4,5,6,7 API

此代码提供了围绕OpenCV DLL的Delphi包装。

对于这些较旧的Delphi版本,CharPCharstring分别映射到AnsiCharPAnsiCharAnsiString。这匹配纯ANSI的OpenCV DLL。 OpenCV中没有Unicode API(至少在我能辨认的范围内)。

如果您希望在Delphi 2009及更高版本中使用此单元,则需要认识到在Delphi 2009中,添加了Unicode支持。这会将CharPCharstring地图的映射分别更改为WideCharPWideCharUnicodeString。这是您遇到的不兼容的原因,因为此单元后面的DLL仍在处理单字节ANSI文本。

此单元最明智的方法可能是将其更改为使用AnsiCharPAnsiCharAnsiString。您可以通过全局搜索执行此操作并在设备中替换。

这将使OpenCV.pas单元再次与DLL匹配。您现在需要小心如何与此OpenCV.pas单元进行交互。接收PAnsiChar参数的函数需要特殊处理。

例如,请考虑以下示例:

Function  cvLoadImage( const filename : PChar; 
    iscolor : integer=1) : PIplImage; cdecl; 

这是原始声明。搜索和替换后,它将如下所示:

Function  cvLoadImage( const filename : PAnsiChar; 
    iscolor : integer=1) : PIplImage; cdecl; 

当您来打电话时,您需要确保通过正确的PAnsiChar。像这样:

var
  FileName: string;
...
image := cvLoadImage(PAnsiChar(AnsiString(FileName)));

您必须从string(映射到UnicodeString)转换为AnsiString,然后才能转换为PAnsiCharPAnsiChar(FileName)。这不会将Unicode字符串转换为ANSI并且将失败。

幸运的是,OpenCV库只有相对较少的接收文本的API。

答案 1 :(得分:1)

参见项目 - github上的Delphi-OpenCV(OpenCV版本 - 2.4.6,环境 - Delphi XE2-XE4)。在Delphi中翻译OpenCV库头文件:https://github.com/Laex/Delphi-OpenCV