我正在编辑一个名为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.
答案 0 :(得分:7)
您引用的OpenCV库在标题的顶部说明了这一点:
用于英特尔开源计算机视觉库的Borland Delphi 4,5,6,7 API
此代码提供了围绕OpenCV DLL的Delphi包装。
对于这些较旧的Delphi版本,Char
,PChar
和string
分别映射到AnsiChar
,PAnsiChar
和AnsiString
。这匹配纯ANSI的OpenCV DLL。 OpenCV中没有Unicode API(至少在我能辨认的范围内)。
如果您希望在Delphi 2009及更高版本中使用此单元,则需要认识到在Delphi 2009中,添加了Unicode支持。这会将Char
,PChar
和string
地图的映射分别更改为WideChar
,PWideChar
和UnicodeString
。这是您遇到的不兼容的原因,因为此单元后面的DLL仍在处理单字节ANSI文本。
此单元最明智的方法可能是将其更改为使用AnsiChar
,PAnsiChar
和AnsiString
。您可以通过全局搜索执行此操作并在设备中替换。
这将使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
,然后才能转换为PAnsiChar
。 不写PAnsiChar(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