![]() |
DLL Funktion(en) von openCV einbinden
Hallo zusammen
ich arbeite schon länger mit Delphi7 und openCV auf XPSp2. So weit funktioniert es auch, nur bei einigen Funktionen komm ich einfach nicht weiter. Kann mal jemand auf die Deklaration und die Anwendung schauen ob ich da einen offensichtlich Fehler drin habe. notwendige funktionen für mein momentanes Problem cvFitLine in OpenCV Version 1.10.1 und auch 2.0a.
Delphi-Quellcode:
das sind die Funktionen die in openCV angesprochen werden, das ganze dann in einer Anwendung sieht so aus
Function cvCreateMemStorage( block_size : integer =0) : PCvMemStorage; cdecl;
// ist in C // CvMemStorage* cvCreateMemStorage( int block_size=0 ); Procedure cvReleaseMemStorage( var storage : PCvMemStorage ); cdecl; // ist in C // void cvReleaseMemStorage( CvMemStorage** storage ); function cvCreateSeq(seq_flags: longInt; header_size: longInt; elem_size: longInt; storage: pCvMemStorage): pCvSeq; cdecl; // ist in C // CvSeq* cvCreateSeq( int seq_flags, int header_size,int elem_size, CvMemStorage* storage ); function cvSeqPush(seq : pCvSeq; aPoint : pCvPoint2D32f): pByte;cDecl; // ist in C // schar* cvSeqPush( CvSeq* seq, void* element=NULL ); function cvGetSeqElem(seq : pCvSeq; index : integer): Pointer;cDecl; // ist in C // char* cvGetSeqElem( const CvSeq* seq, int index ); // das sind die funktionen die funktionieren wie ich es erwarte // hier bekomme ich Fehler procedure cvFitLine(points : pcvArr; dist_Type : longInt; param : double; reps: double; aeps: double; line: pSingle);cdecl; // ist in C //void cvFitLine( const CvArr* points, int dist_type, double param, double reps, double aeps, float* line );
Delphi-Quellcode:
wenn der Aufruf cvFitLine auskommentiert ist, kann ich genau die Punkte aus der Sequenz auslesen wie ich sie rein gepushed habe!
procedure TForm1.seq;
var m, b: single; store : pCvMemStorage; seq : pCvSeq; sInfo : string; pErg : pByte; aPointer : Pointer; myPoint: CvPoint2D32f; pPoint : pCvPoint2D32f; row,col, elem : byte; line : array[0..4] of single; begin m := 0.5; b:=2; store := cvCreateMemStorage(0); sInfo := ''; seq := cvCreateSeq(0, sizeOf(CvSeq), sizeOf(CvPoint2D32f), store); for row:=0 to 0 do for col:= 0 to 3 do begin myPoint.x := 0.05+col; myPoint.y := m*myPoint.x+b; pErg := cvSeqPush(seq, @myPoint); end; cvFitLine(seq, 0, 0, 0.01,0.01, @line[0]); sInfo := ''; for elem := 0 to seq.total-1 do begin pPoint := cvGetSeqElem(seq, elem); sInfo := sInfo + Format(' %5.2f %5.2f'+#13#10,[pPoint^.x, pPoint^.y]); end; Label2.Caption := sInfo; cvReleaseMemStorage(store); end; Bei Bedarf kann ich auch das gesamte projekt posten. Gruß Stefan PS.: wer openCV runterladen will das gibts hier: ![]() |
Re: DLL Funktion(en) von openCV einbinden
Du musst in cvFitLine points auch in Delphi ebenfalls als const übergeben.
Delphi-Quellcode:
procedure cvFitLine(const points : pcvArr; dist_Type : longInt; param : double; reps: double; aeps: double; line: pSingle);cdecl;
|
Re: DLL Funktion(en) von openCV einbinden
Danke für die Antwort!
Du meinst in der Deklaration von cvFitLine? oder beim Aufruf (???) bei der Deklaration
Delphi-Quellcode:
gibts keine Änderung weder mit Version 2.0a noch mit 1.1.0.1
procedure cvFitLine(const points : pcvArr; dist_Type : longInt; param : double; reps: double; aeps: double; line: pSingle);cdecl;
// ist in C //void cvFitLine( const CvArr* points, int dist_type, double param, double reps, double aeps, float* line ); |
Re: DLL Funktion(en) von openCV einbinden
in der Deklaration. Das wäre ein offensichtlicher Fehler gewesen.
Gut, ohne dass ich openCV kenne, fallen mir noch ein paar Sachen auf: Was geht denn nicht - schmiert das Programm ab oder liefert es falsche Ergebnisse? Ich sehe nicht, wo du das (vermutliche) Ergebnis Line verwendet wird. Und warum hat es 5 singles? |
Re: DLL Funktion(en) von openCV einbinden
Hallo,
cvFitLine(seq, 0, 0, 0.01,0.01, @line[0]); laut Deklaration function cvCreateSeq ... : pCvSeq ist seq vom Typ pCvSeq cvFitLine(points : pcvArr; will aber ein pcvArr Ich habe keine Lust, mir das ganze Teil herunterzuladen, die verwendeten Daten-Typen könntest du ja mal posten ;) Ausserdem übergibst du mit @line[0] einen Pointer ? Muss es nicht cvFitLine(seq, 0, 0, 0.01,0.01, line[0]); heissen ? Heiko |
Re: DLL Funktion(en) von openCV einbinden
Die 5 singles sind natürlich ein versehen! aber unabhängig davon stürzt die Funktion cvFitLine ab.
Zitat:
Delphi-Quellcode:
als auch mit
line: array[0..3] of single;
Delphi-Quellcode:
cvFitLine stürzt ab
line: array[0..3] of double;
mit Runtime Error bei verwendung von libcv200.dll bzw. libcxcore200.dll. und mit der Fehlermeldung "Unsupported format or combination of formats (Input sequence must consist of 2d points or 3d points) in function cvFitLine, .\cvlinefit.cpp(665)" bei verwendung von cv110.dll bzw. cxcore110.dll. @Jaynder Was machst Du denn mit openCV, vielleicht können wir mal unsere umgesetzten Funktionalitäten abgleichen. |
Re: DLL Funktion(en) von openCV einbinden
Hier sind mal die definitionen der verwendeten Datentypen
Delphi-Quellcode:
welche Datentypen soll ich noch posten?
type
PCvSeqBlock = ^CvSeqBlock; CvSeqBlock = record prev : PCvSeqBlock; next : PCvSeqBlock; start_index : longint; count : longint; data : Pchar; end; PCvSeq = ^CvSeq; CvSeq = record flags : longint; header_size : longint; h_prev : PCvSeq; h_next : PCvSeq; v_prev : PCvSeq; v_next : PCvSeq; total : longint; elem_size : longint; block_max : Pchar; ptr : Pchar; delta_elems : longint; storage : PCvMemStorage; free_blocks : PCvSeqBlock; first : PCvSeqBlock; end; Type PCvMemStorage = ^TCvMemStorage; P2PCvMemStorage = ^PCvMemStorage; CvMemStorage = Record signature : integer; bottom : PCvMemBlock; //* first allocated block */ top : PCvMemBlock; //* current memory block - top of the stack */ parent : PCvMemStorage; //* borrows new blocks from */ block_size: integer; //* block size */ free_space: integer; //* free space in the current block */ end; type CvPoint2D32f = record x : Single; y : Single; end; TCvPoint2D32f = CvPoint2D32f; PCvPoint2D32f = ^TCvPoint2D32f; end; cvArr, cvMat/cvSeq, iplImage bauen alle aufeinander auf bei vielen funktionen die ein pIplImage erwarten steht in der deklaration auch "nur" ein pCvArr, deshalb denke ich dass es so richtig ist, aber ganz sicher bin ich mir nicht! das mit der line ist uU ein folgeproblem das aber denke ich noch nicht zum tragen kommt. Wenn ein string übergeben werden muss hat es immer ganz gut funktioniert wenn ich @myStr[0] statt pChar übergeben habe deshalb habe ich es analog dazu so gemacht @line[0] als pointer auf das erste element. |
Re: DLL Funktion(en) von openCV einbinden
Zitat:
Was ist denn Zitat:
[Add] poste doch mal die komplette Beschreibung der Parameterliste |
Re: DLL Funktion(en) von openCV einbinden
Hallo,
wie ist das Alignment der Record ? Versuche testweise mal packed record. Kennst du den Link hier schon ? ![]() Heiko |
Re: DLL Funktion(en) von openCV einbinden
@hoika ja den link kenn ich. aber da ist tote hose, keine members und nichts, eigentlich schade! bei yahoo gibts eine openCV gruppe in der etwas mehr los ist, aber da weiß auch niemand was, die sind auch nicht auf delphi ausgerichtet.
das mit dem packed record hab ich ausprobiert und hat nix gebracht ich hab dann auch noch mal geschaut was das bringen könnte. also so wie ich das verstanden habe eine speicherung des records immer an einer 32 -bit bzw 4 byte grenze - aber wenn ich eh nur singels (4Byte) oder doubles (8byte) verwende hat das doch keinen einfluss! Oder hab ich das falsch verstanden? |
Re: DLL Funktion(en) von openCV einbinden
Hallo,
stimmt ;) Single ist ja 32 Bit. Hast du den @line[] ersetzt ? Ausserdem kannst du ja mal ein c++-Bsp. mit dem Fit posten, vor allem die Vorbereitung. Habe keine Lust, hier was zu installieren. Heiko |
Re: DLL Funktion(en) von openCV einbinden
Liste der Anhänge anzeigen (Anzahl: 1)
here we are again!
war ein bisschen gegoogel bis ich ein c beispiel fand! allerdings mit einigermaßen unleserlichen komentaren (zumindest für den dem japanisch nicht mächtigen)
Delphi-Quellcode:
Was mir aufgefallen ist
#include <cv.h>
#include <stdio.h> #include <math.h> float myLinearity(CvSeq *); int main(void) { int i; double fx[] = {0.0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1.0}; double fy[] = {3.874, 3.202, 2.781, 2.49, 2.274, 2.156, 1.934, 1.74, 1.653, 1.662}; float *line = new float[4]; float linearity=0.0f; //入れ物の確保 CvMemStorage* storage = cvCreateMemStorage(0); //3次元の場合はCV_32FC2がCV_32FC3に、CvPoint2D32fがCvPoint3D32fになる CvSeq* point_seq = cvCreateSeq( CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage ); for (i=0; i<10; i++){ //値の追加はcvSeqPush cvSeqPush(point_seq, &cvPoint2D32f(fx,fy)); } linearity = myLinearity(point_seq); cvFitLine(point_seq,CV_DIST_L2,0,0.01,0.01,line); fprintf(stdout,"v=(%f,%f),vy/vx=%f,(x,y)=(%f,%f), Linearity=%f\n",line[0],line[1],line[1]/line[0],line[2],line[3],linearity); cvClearSeq(point_seq); cvReleaseMemStorage(&storage); return 0; } //大津の直線度 float myLinearity(CvSeq *seq) { int i; CvPoint2D32f *p; float *x = new float[seq->total]; float *y = new float[seq->total]; float x_bar=0.0, y_bar=0.0; float u11=0.0, u20=0.0, u02=0.0; float linearity=0.0; //吸い出し cvGetSeqElemでポインタを得るのでキャストして取得 for (i=0; i < seq->total; i++){ p=(CvPoint2D32f*)cvGetSeqElem(seq,i); x=p->x; y=p->y; } //x_bar, y_bar for (i=0; i < seq->total; i++){ x_bar+=x; y_bar+=y; } x_bar/=seq->total; y_bar/=seq->total; //セントラルモーメント for (i=0; i < seq->total; i++){ u11+=((x-x_bar)*(y-y_bar)); u20+=pow(x-x_bar,2.0f); u02+=pow(y-y_bar,2.0f); } u11/=seq->total; u20/=seq->total; u02/=seq->total; //直線度の算出 linearity = sqrt(4*pow(u11,2.0f)+pow(u20-u02,2.0f))/(u20+u02); return linearity; } 1. cvCreateSeq wird mit CV_32FC2 als 1.parameter aufgerufen! das ergibt bei mir aber einen Fehler! aber das was mit der pSeq gemacht wird mache ich genau gleich und das funktioniert! (ist natürlich keine Garantie) 2. cvFitLine wird als Dist 2.Par CV_DIST_L2 mitgegeben, hat aber auch keine Besserung gebracht. Im Anhang habe ich mal noch den Source Code von cvFitLine reingepackt, dort wird untersucht ob der Pointer auf das line Array Nil ist! Wie ich mein Line Array definiere ist dann also (noch) nicht für den Fehler verantwortlich, (wenn überhaupt). Gruß Stefan |
Re: DLL Funktion(en) von openCV einbinden
Wenn ich nochmal auf die Fehlermeldung
Zitat:
cvFitLine bekommt points : pcvArr
Delphi-Quellcode:
du übergibst aber ein pCvSeq
procedure cvFitLine(points : pcvArr; dist_Type : longInt; param : double; reps: double; aeps: double; line: pSingle);cdecl;
// ist in C //void cvFitLine( const CvArr* points, int dist_type, double param, double reps, double aeps, float* line );
Delphi-Quellcode:
Liegt es vielleicht daran?
seq : pCvSeq;
begin ... seq := cvCreateSeq(0, sizeOf(CvSeq), sizeOf(CvPoint2D32f), store); ... cvFitLine(seq, 0, 0, 0.01,0.01, @line[0]); Und wieso übersetzt Delphi das eigentlich ohne Fehler? |
Re: DLL Funktion(en) von openCV einbinden
@Jaynder Wenn man das mit dem C Code vergleicht mache ich doch genau das gleiche in Bezug auf die 2 Einwände die Du machst!
1. Schrottige Daten: wenn ich die pSeq mit Punkten fülle und dann zur Kontrolle mit cvGetSeqElem genau den richtigen Daten Typ mit den richtigen Werten Lesen kann, dann können die Daten doch nicht so schrottig sein. 2. falscher Übergabe Typ: das ist auch genau wie in dem C-Beispiel! Es wird eine Sequenz vom Typ pCvSeq erzeugt und an cvFitLine übergeben genau wie hier:
Delphi-Quellcode:
in dem Beispiel übergebe ich ja auch ein pIplImage an eine routine die nur pCvArr nimmt und es funktioniert wunderbar.
var pLinkeEcke, ptmp1 : pIplImage;
sc : cvScalar; ... ... ptmp1 := cvCreateImage(cvSize_(pLinkeEcke.Width, pLinkeEcke.Height), 8, 1); cvAddS(pLinkeEcke, sc, pTmp1, nil); // definition von cvAddS in C void cvAddS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL ); Viel schlimmer finde ich es dass der Aufruf von cvCreateSeq
Delphi-Quellcode:
als seq_flag nur die 0 ohne Fehler nimmt! Und damit kann die Sequenz von cvFitLine nicht mehr richtig erkannt werden, was die angeblich schrottigen Daten erklären würde!
// CvSeq* cvCreateSeq( int seq_flags, int header_size,int elem_size, CvMemStorage* storage );
in der Doku steht dazu: Zitat:
Ich bin ratlos! Trotzdem Danke! Ich glaube es ist das beste mal das Entwicklerteam zu fragen ob die meine Fehler nachvollziehen können. Gruß Stefan |
Re: DLL Funktion(en) von openCV einbinden
Das ist schon komisch, aber c-Beispiele können ja aucg Fehler enthalten.
Trotzdem nochmal die Frage: wieso übersetzt Delphi den cvFitLine-Call mit dem abweichenden Typen? |
Re: DLL Funktion(en) von openCV einbinden
Nachtrag: ich habe im Netz
![]()
Code:
Jürgen
625 CV_IMPL void
626 cvFitLine2D( CvPoint2D32f * points, int count, CvDisType dist, 627 void *param, float reps, float aeps, float *line ) |
Re: DLL Funktion(en) von openCV einbinden
Der Grund weshalb das compiliert wird ist die Deklaration von pCvArr!
Delphi-Quellcode:
Deshalb wird man alles pointer ähnliches ohne Fehler übergeben können.
{ CvArr* is used to pass arbitrary array-like data structures
into the functions where the particular array type is recognized at runtime } // CvArr = void; PCvArr = Pointer; P2PCvArr = ^PCvArr; |
Re: DLL Funktion(en) von openCV einbinden
Zu dem Nachtrag: In openCV 1.1 und auch 2.0a sind die beiden Routinen cvFitLine2D und auch cvFitLine3D in cvFitLine gekapselt oder so was in der Art.
Das heißt für die beiden 2D/3D routinen gibts gar keinen Einsprungpunkt. Also nur noch cvFitLine. Version 0.97 (oder wars 0.98??) war ziemlich lange aktuell und viele Beispiele beziehen sich noch darauf ohne dass dazugeschrieben steht mit welcher Version von openCV gearbeitet wurde. |
Re: DLL Funktion(en) von openCV einbinden
Ok, das mit dem nackten Pointer ist zwar übel, lässt aber wohl nicht vermeiden. Aber das Problem dann doch eindeutig beim cvCreateSeq, wie du schon erkannt hast.
Zitat:
|
Re: DLL Funktion(en) von openCV einbinden
Wenn ich cvCreateSeq mit dem Richtigen Parameter aufrufe bekomme ich einen Runtime Error.
Der "richtige" Parameter mit Namen CV_32F2 ist einfach die byte anzahl 32=4byte und das 2x wegen 2D sind 8 byte Wenn ich cvCreateSeq mit 0 für den typ aufrufe wird flags $42990000 in meinem OpenCV_200.pas gibt es für die Bild/Matrizen/cvArr/Squenzen Magic Values das sind
Delphi-Quellcode:
dann habe ich mal in den C Sourcen nach den Konstanten gesucht und bin auf das gestoßenCV_MAT_MAGIC_VAL = $42420000; CV_MATND_MAGIC_VAL = $42430000; CV_HIST_MAGIC_VAL = $42450000; CV_STORAGE_MAGIC_VAL = $42890000; // dann auch CV_SEQ_MAGIC_VAL = $42990000; // wie zu erwarten war
Delphi-Quellcode:
für mich sieht das aus als ob man mit diesen Konstanten also
#define CV_SEQ_MAGIC_VAL 0x42990000
#define CV_SET_MAGIC_VAL 0x42980000 #define CV_SEQ_ELTYPE_BITS 9 #define CV_SEQ_ELTYPE_MASK ((1 << CV_SEQ_ELTYPE_BITS) - 1) #define CV_SEQ_ELTYPE_POINT CV_32SC2 #define CV_SEQ_ELTYPE_CODE CV_8UC1 #define CV_SEQ_ELTYPE_GENERIC 0 #define CV_SEQ_ELTYPE_PTR CV_USRTYPE1 #define CV_SEQ_ELTYPE_PPOINT CV_SEQ_ELTYPE_PTR #define CV_SEQ_ELTYPE_INDEX CV_32SC1 #define CV_SEQ_ELTYPE_GRAPH_EDGE 0 #define CV_SEQ_ELTYPE_GRAPH_VERTEX 0 #define CV_SEQ_ELTYPE_TRIAN_ATR 0 #define CV_SEQ_ELTYPE_CONNECTED_COMP 0 #define CV_SEQ_ELTYPE_POINT3D CV_32FC3 #define CV_SEQ_KIND_BITS 3 #define CV_SEQ_KIND_MASK (((1 << CV_SEQ_KIND_BITS) - 1)<<CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_GENERIC (0 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_CURVE (1 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_BIN_TREE (2 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_GRAPH (3 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_KIND_SUBDIV2D (4 << CV_SEQ_ELTYPE_BITS) #define CV_SEQ_FLAG_SHIFT (CV_SEQ_KIND_BITS + CV_SEQ_ELTYPE_BITS) #define CV_SEQ_FLAG_CLOSED (1 << CV_SEQ_FLAG_SHIFT) #define CV_SEQ_FLAG_SIMPLE (2 << CV_SEQ_FLAG_SHIFT) #define CV_SEQ_FLAG_CONVEX (4 << CV_SEQ_FLAG_SHIFT) #define CV_SEQ_FLAG_HOLE (8 << CV_SEQ_FLAG_SHIFT) #define CV_GRAPH_FLAG_ORIENTED (1 << CV_SEQ_FLAG_SHIFT) #define CV_GRAPH CV_SEQ_KIND_GRAPH #define CV_ORIENTED_GRAPH (CV_SEQ_KIND_GRAPH|CV_GRAPH_FLAG_ORIENTED) #define CV_SEQ_POINT_SET (CV_SEQ_KIND_GENERIC| CV_SEQ_ELTYPE_POINT) #define CV_SEQ_POINT3D_SET (CV_SEQ_KIND_GENERIC| CV_SEQ_ELTYPE_POINT3D) #define CV_SEQ_POLYLINE (CV_SEQ_KIND_CURVE | CV_SEQ_ELTYPE_POINT) #define CV_SEQ_POLYGON (CV_SEQ_FLAG_CLOSED | CV_SEQ_POLYLINE ) #define CV_SEQ_CONTOUR CV_SEQ_POLYGON #define CV_SEQ_SIMPLE_POLYGON (CV_SEQ_FLAG_SIMPLE | CV_SEQ_POLYGON ) #define CV_SEQ_CHAIN (CV_SEQ_KIND_CURVE | CV_SEQ_ELTYPE_CODE) #define CV_SEQ_CHAIN_CONTOUR (CV_SEQ_FLAG_CLOSED | CV_SEQ_CHAIN) #define CV_SEQ_POLYGON_TREE (CV_SEQ_KIND_BIN_TREE | CV_SEQ_ELTYPE_TRIAN_ATR) #define CV_SEQ_CONNECTED_COMP (CV_SEQ_KIND_GENERIC | CV_SEQ_ELTYPE_CONNECTED_COMP) #define CV_SEQ_INDEX (CV_SEQ_KIND_GENERIC | CV_SEQ_ELTYPE_INDEX)
Delphi-Quellcode:
die flags haargenau so einstellen muss dass es halt passt!
MAGIC or typ or größe or weissNicht
Ich melde mich wieder wenn ich mehr weiß! Die Spur ist auf jeden Fall mal interessant! Gruß und Ciao |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz