Wrapper für FLANN-Bibliothek - ideal für Nearest-Neighbour-Problem

  • Mein alter Thread zum Thema ist irgendwie verschwunden.

    Daher hier einfach noch einmal ohne große Worte die UDF hochgeladen.

    Was kann man damit machen?

    • sauschnell zu einer Koordinate (egal wieviele Dimensionen) seinen nächsten Nachbar finden
    • Alle Punkte aus der Menge welche in einem bestimmten Radius um eine Koordinate liegen herausfiltern.
  • Die UDF wäre genau das, was ich suche. Leider funktioniert sie bei mir nicht.

    Das Example stürzt mit folgender Ausgabe ab:

    !>11:20:28 AutoIt3.exe ended.rc:-1073741819

    Innerhalb des UDF bricht er innerhalb der Funktion "_flann_find_nearest_neighbors" beim Aufruf von

    Code
    DllCallAddress("INT", $p_A, _
                "PTR", $t_DataSet[0], "INT", $t_DataSet[1], "INT", $t_DataSet[2], _
                "PTR", $t_TestSet[0], "INT", $t_TestSet[1], _
                "PTR", DllStructGetPtr($p_indices), "PTR", DllStructGetPtr($p_dists), _
                "INT", $nn, "Ptr", DllStructGetPtr($p_DEFAULT_FLANN_PARAMETERS))

    ab.

    Woran kann das liegen?

  • Das Problem tritt bei mir auch auf. Allerdings nur wenn ich es als 32-Bit Programm ausführe.

    Also als erstes mal #AutoIt3Wrapper_UseX64=y an den Anfang des Skriptes schreiben.

    Ansonsten kann ich hier gerade nicht viel testen und blöderweise ist die Seite zur API-Dokumentation der Bibliothek tot.

    Ich vermute mal rein ins blaue und denke, dass die DLL Abhängigkeiten zu den >>Visual C++ - Runtimes<< hat und die entsprechenden Librarys nicht vorliegen.

    Diese also mal installieren (was ich hier gerade nicht kann) und schauen ob es dann klappt, wenn es nicht bereits als X64-Skript funktionert.

  • Ich denke es liegt an drei Dingen:

    1.) $p_A ist immer ein Null-Pointer, weil du für den Parameter lpProcName " " angegeben hast.

    Local Static $p_A = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $p_FLANNDLL, "str", " ")[0]

    x86: $p_A --> 0x00000000

    x64: $p_A --> 0x0000000000000000

    Richtig wäre wohl:

    Local Static $p_A = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $p_FLANNDLL, "str", "flann_find_nearest_neighbors")[0]

    2.) Hier gibst du evtl. nicht die korrekten Typen an.

    AutoIt
        DllCallAddress("INT", $p_A, _
                "PTR", $t_DataSet[0], "INT", $t_DataSet[1], "INT", $t_DataSet[2], _
                "PTR", $t_TestSet[0], "INT", $t_TestSet[1], _
                "PTR", DllStructGetPtr($p_indices), "PTR", DllStructGetPtr($p_dists), _
                "INT", $nn, "Ptr", DllStructGetPtr($p_DEFAULT_FLANN_PARAMETERS))

    Erwartet wird: EXPORTED int flann_find_nearest_neighbors(float* dataset, int rows, int cols, float* testset, int tcount, int* result, float* dists, int nn, FLANNParameters* flann_params)

    Hier habe ich die Exports gefunden (ab Zeile 373):

    https://git.rwth-aachen.de/till.hofmann/o…13c7c6dbe86aba0

    3.) $a_DataSet enthält Double-Werte, $a_TestSet aber Int32-Werte... sollten da nicht auch Double-Werte drin sein?

  • So jetzt komme ich auch mal wieder dazu.

    1.) $p_A ist immer ein Null-Pointer, weil du für den Parameter lpProcName " " angegeben hast.

    Wie ist das denn reingerutscht? :thumbup:
    Hab mir die Zip runtergeladen - da war es korrekt drin.
    Aber auf meiner Festplatte hatte ich noch eine andere Version drin liegen wo das fehlte - keine Ahnung wie das mal raus bzw. wieder reingekommen ist.

    Die Version die jetzt oben liegt sollte aber richtig sein.

    2.) Hier gibst du evtl. nicht die korrekten Typen an.

    Wo genau sollen die Typen nicht richtig sein?
    Bin es nochmal durchgegangen und sehe da bislang keinen Fehler.

    3.) $a_DataSet enthält Double-Werte, $a_TestSet aber Int32-Werte... sollten da nicht auch Double-Werte drin sein?

    In _FLANN_Data2C wird das Array im Speicher befüllt - jeweils als Double-Wert.
    Eventuelle interne Int-Werte eines AutoIt-Varianttypes werden an dieser Stelle implizit zu double gecastet.

  • Hab mir die Zip runtergeladen - da war es korrekt drin.

    Ich habe sie mir soeben auch noch mal runtergeladen... und da ist es der Fehler immer noch drin!

    Local Static $p_A = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $p_FLANNDLL, "str", " ")[0]

    Habe es nun wieder so geändert:

    Local Static $p_A = DllCall($h_KRNL32, "ptr", "GetProcAddress", "handle", $p_FLANNDLL, "str", "flann_find_nearest_neighbors")[0]

    Aber... ich bekomme trotzdem die gleiche Fehlermeldung wie karlgustavv .

    @@_Debug_line 40 var: $p_A --> 0x501F0510

    !>18:57:12 AutoIt3.exe ended.rc:-1073741819

    Wo genau sollen die Typen nicht richtig sein?

    Code
    DllCallAddress("INT", $p_A, _                                                                  ;~ EXPORTED int flann_find_nearest_neighbors(
           "PTR", $t_DataSet[0], "INT", $t_DataSet[1], "INT", $t_DataSet[2], _                     ;~ float* dataset, int rows, int cols,
           "PTR", $t_TestSet[0], "INT", $t_TestSet[1], "PTR", DllStructGetPtr($p_indices), _       ;~ float* testset, int tcount, int* result,
           "PTR", DllStructGetPtr($p_dists), "INT", $nn, _                                         ;~ float* dists, int nn,
           "Ptr", DllStructGetPtr($p_DEFAULT_FLANN_PARAMETERS))                                    ;~ FLANNParameters* flann_params)

    Hm, schein soweit aber korrekt zu sein... (wenn ptr == float*)... aber auch so schmiert AutoIt trotzdem ab:

    https://docs.rs/flann-sys/0.1.…_neighbors.html

    Code
    DllCallAddress("INT", $p_A, _                                                                  ;~ EXPORTED int flann_find_nearest_neighbors(
           "float*", $t_DataSet[0], "INT", $t_DataSet[1], "INT", $t_DataSet[2], _                  ;~ float* dataset, int rows, int cols,
           "float*", $t_TestSet[0], "INT", $t_TestSet[1], "INT*", DllStructGetPtr($p_indices), _   ;~ float* testset, int tcount, int* result,
           "float*", DllStructGetPtr($p_dists), "INT", $nn, _                                      ;~ float* dists, int nn,
           "INT_PTR", DllStructGetPtr($p_DEFAULT_FLANN_PARAMETERS))                                ;~ FLANNParameters* flann_params)

    Evtl. stimmen die DEFAULT_FLANN_PARAMETERS nicht:

    https://docs.rs/flann-sys/0.0.…Parameters.html

    Code
    Global Const $tag_FLANNParameters = "struct;INT algorithm;INT checks;FLOAT cb_index;FLOAT eps;INT trees;INT leaf_max_size;INT branching;INT iterations;INT centers_init;FLOAT target_precision;FLOAT build_weight;FLOAT memory_weight;FLOAT sample_fraction;UINT table_number_;UINT key_size_;UINT multi_probe_level_;INT log_level;LONG random_seed;endstruct"
  • Ich habe sie mir soeben auch noch mal runtergeladen... und da ist es der Fehler immer noch drin!

    :D - tja sowas kommt dabei raus, wenn man auf Arbeit mal kurz ne Pause macht und denkt: schau ich mal kurz bei AutoIt.de vorbei.

    Ich hatte wahrscheinlich noch eine vorherige Version im Downloadverzeichnis und dachte anscheinend es war diese welche ich runtergeladen habe.

    Mit deinen Typen hast du vollkommen Recht!
    Der DLLCallAdress-Aufruf ist aber so korrekt. Was hingegen nicht korrekt ist, ist der Name der aufzurufenden Funktion.

    Diese sollte flann_find_nearest_neighbors_double lauten, da das Array ja Double ist und nicht Float.

    Hab diese Variante jetzt hochgeladen.

    So läuft es bei mir zumindest als X64-Skript. Nur bei X86 kackt es weiterhin ab.
    Ich gebe zu mir fehlt da bisschen die Zeit und auch die Lust da mich wieder tiefer einzugraben solange es ja als X64 funzt.

    Aber danke dir schonmal für deine hierin investierte Zeit :thumbup: