Problem z funkcją pobierania ramek z własnej dll

Tematyka związana z tworzeniem aplikacji w LabVIEW do obsługi wizji oraz wszelkich operacji na obrazie.
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

Korzystając z pierwszej wypowiedzi witam serdecznie .

Od razu przepraszam za ewentualne "lamerstwo" - mimo dojrzałego wieku, w LabVIEW stawiam pierwsze kroki.

Nasza firma zajmuje się analizą obrazu w 3D, a od niedawna też w 2D (zazwyczaj jest odwrotnie - my zrobiliśmy "nawigację 3D" dla medycyny, a że nie chce się sprzedawać to "suwmiarkę 3D" dla przemysłu ... też słabo, więc wskoczyliśmy w 2D :) ) Aplikacja ma za zadanie rozpoznawać obiekty (śrubki) i wykorzystuje nasze własne algorytmy analizy obrazu (okazały się sprawniejsze od dostępnych na rynku).
Chciałem więc sprawdzić jak można przerzucić działający system do LabVIEW ... może udostępnić dla szerszego grona urzytkowników.
I tu pora skończyć chwalenie się i przejść do konkretów opisujących problem.

Mam problem z jedną z funkcji do pobierania ramek z kamery, która to funkcja dostępna jest w napisanej przez kolegę dll'ce (pisane w C++ BDS)
Funkcja "GrabFrame" zwraca wskaźnik do tablicy 2 wymiarowej HxW (w naszym przypadku kamera 1024x768). Niestety albo nie mogę ustawić parametrów w "Call Library Function Note", albo nie wiem jak wykorzystać referencję do odczytania takiej tablicy z pamięci.

Nagłowek bibliotekiwygląda następująco:

Kod: Zaznacz cały

#ifndef CameraH
#define CameraH

typedef unsigned char UINT8;

extern "C" __declspec(dllexport) void* __stdcall TCamera_Create();
extern "C" __declspec(dllexport) void __stdcall TCamera_Destroy(void* p);
extern "C" __declspec(dllexport) int __stdcall TCamera_CamInit(void* p, int CamNum, int* Height, int* Width, int* SerialNum);
extern "C" __declspec(dllexport) int __stdcall TCamera_CamStop(void* p);
extern "C" __declspec(dllexport) int __stdcall TCamera_GrabFrame(void* p, UINT8** buff8);
extern "C" __declspec(dllexport) void __stdcall TCamera_SetExposure(void* p, int exposure);

#endif
A tak wygląda Vi - funkcja GrabFrame pomiędzy czerwonymi liniami.
Obrazek
Obrazek
Obrazek

W tej wersji programu Indicator "buff8 2" zwraca jakiś wskaźnik do jakiegoś miejsca w pamięci, ale nie wiem co z tym dalej mogę zrobić - jak pobrać stamtąd tablicę z danymi?

W wersji drugiej
Obrazek
Obrazek
Obrazek

W tej wersji programu tablica "buff8 2" jest niestety pusta (same zera) - jak pobrać tablice z danymi?

Dodam, że kolega w C++ wywołuje funkcję GrabFrame ze wskaźnikiem do wskaźnika do tablicy. Drugi kolega w Delphi zrobił test - zadeklarował tablicę 1 elementową, wywołał funkcję GrabFrame ze wskaźnikiem do tej tablicy i w odpowiedzi otrzymał w tej tablicy wskaźnik do tablicy HxW (on wiedział co z tym dalej zrobić) - czyli u niego gra. Jak to zrobić w LabVIEW?

Z góry dziękuję za wszelkie podpowiedzi.
Załączniki
srubki.rar
Załączam pliki dll + vi oraz wymaganą resztę
(1.88 MiB) Pobrany 438 razy
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

W Twoim przypadku poprawna jest wersja 2, z jadną małą poprawką - ponieważ tablica zdefiniowana jest jako podwójny wskaźnik, zamiast "Array Data Pointer" musisz użyć "Array Handle" (czy jakoś tak - piszę z pamięci). "Handle" w terminologii LabVIEW oznacza właśnie wksaźnik do wskaźnika.
Po ikonkach poznaję, że użyłeś automatycznego importu DLL-ki. Z doświadczenia - nie radzę. Pomimo, że uzywam dużo odwołań do zewnętrzych DLL jeszcze NIGDY nie zdarzyło mi się by taki import był w 100% poprawny, a poprawek jest zawsze tyle, że zwykle szybciej robić to ręcznie, albo napisać coś co zrobi to półautomatycznie dla danego przypadku.
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

Niestety nie w każdym przypadku wynik jest ten sam (jak na obrazku dla wersji 2) - czyli Array Data Pointer, Array Handle i Array Handle Pointer działają w tym przypadku identycznie ... albo dają identyczny rezultat.

Może jakieś dodatkowe podpowiedzi...?
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

jakbyś zapisał w 8.2 to mógłbym się dokładniej przyjrzeć. I razem z VI dla pszczególnych funkcji dll (przynajmniej tych ze screena)
Awatar użytkownika
wino
Posty: 549
Rejestracja: 23 gru 2005 00:00
Wersja środowiska: Nie mam LabVIEW
Lokalizacja: Kraków

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: wino »

Może pomoże zmiana typu danych z Array Hendle, na opcję Adapt To Data Type(chyba jest taka opcja). Wtedy wyjście/wyjście funkcji zaadaptuje się do podpiętego typu danych. Jeśli podepniesz dwuwymiarową tablicę na wejściu bloczka to wybrana funkcja na wyjściu zwróci wypełnioną tablicę.
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

Załączyłem pliki w wersji 8.2
Biblioteki camera, camera1 i camera2 (bo takie katalogi można tam znaleźć) są praktycznie identyczne. Jedyna różnica to dodana jedna funkcja TCamera_GrabFrame_forArek(void* p, unsigned char* buff8, int H, int W), która miała być prostszą wersją poprzedniej, a z którą mam ten sam problem - w tych VI'ach jej nie użyłem.
Załączniki
srubki1 Folder.rar
(55.83 KiB) Pobrany 431 razy
srubki2 Folder.rar
(181.73 KiB) Pobrany 494 razy
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

wino pisze:Może pomoże zmiana typu danych z Array Hendle, na opcję Adapt To Data Type(chyba jest taka opcja). Wtedy wyjście/wyjście funkcji zaadaptuje się do podpiętego typu danych. Jeśli podepniesz dwuwymiarową tablicę na wejściu bloczka to wybrana funkcja na wyjściu zwróci wypełnioną tablicę.
Zmieniłem w 2 wersji na Adapt To Type (we wszystkich 3 możliwych opcjach) i w każdej efekt końcowy jest identyczny jak dotychczas - tablica 1024x768 z samymi zerami. :-\
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

Adapt to type nie powinno zadziałać w tym przypadku.

Rozumiem, że wszystkie kombinacje typu podawania tablicy i wywołania (C i stdcall) nie działają. Sugeruję sprawdzić jeszcze zmianę wątku wywołania (z "Run in UI thread" na Reentrant). W przypadku podwójnego wskaźnika musi być "Array Handle" i kropka. Ja zwykle używam pojedyńczego wskaźnika - tak jak w funkcji "for Arek". Ale jest jedno ważne zastrzeżenie - funkcja musi pod ten adres wrzucać dane bez żadnej alokacji pamięci (musi zakładać, że wystarczająca ilość pamięci jest pod podanym adresem zaalokowana). Programiści C++ zwykle mają opory w tej sytuacji... Używam wyłącznie wywołania typu C (stdcall tylko w przypadku dll-ek winapi) i jako Reentrant (kto by chciał pakować coś jeszcze do wątku interfejsu).

Zakładam, że DLL-ka skompilowana jest jako 32-bitowa.
Weź funkcję z deklaracją UINT8** i najpierw skonfiguruj parametr buff jako I32 "Value" i zobacz co wychodzi. Powinno być 0 (a dokładniej na wyjściu powinno być to samo co na wejściu. Jeżeli nie jest to DLL-ka jest źle zrobiona. Następnie zmień Value na "Pointer to Value" i zobacz co wychodzi. Powinna wychodzić liczba zmienna z wywołania na wywołanie. Jeżeli jest to dobra nasza. Dalej opiszę jak znajdę odpowiedni materiał, bo z pamięci to mogę namieszać.
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

Po pierwsze bardzo dziękuję kolegom za zaangażowanie w mój problem (szczególnie vugie - chapeau bas!).
...wszystkie kombinacje typu podawania tablicy i wywołania (C i stdcall) nie działają
- dokładnie tak.
Sugeruję sprawdzić jeszcze zmianę wątku wywołania (z "Run in UI thread" na Reentrant)
- ten sam efekt.
Weź funkcję z deklaracją UINT8** i najpierw skonfiguruj parametr buff jako I32 "Value" i zobacz co wychodzi. Powinno być 0 (a dokładniej na wyjściu powinno być to samo co na wejściu. Jeżeli nie jest to DLL-ka jest źle zrobiona. Następnie zmień Value na "Pointer to Value" i zobacz co wychodzi. Powinna wychodzić liczba zmienna z wywołania na wywołanie.
Gdy ustawiłem buff jako I32 Value na wyjściu jest to samo co na wejściu. Niestety gdy zmienię na Pointer to Value efekt jest ten sam - na wyjściu to samo co na wejściu. :-\

Odnośnie funkcji "GrabFrame for Arek" to nie do końca rozumiem problemu z alokacją pamięci. Przecież ja w LabVIEW tworzę tablicę (podpięta do wejścia funkcji), którą funkcja ma tylko wypełnić danymi...?... no właśnie, dlaczego to też nie działa? - wiesza LabView...
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

smiga pisze:Odnośnie funkcji "GrabFrame for Arek" to nie do końca rozumiem problemu z alokacją pamięci. Przecież ja w LabVIEW tworzę tablicę (podpięta do wejścia funkcji), którą funkcja ma tylko wypełnić danymi...?... no właśnie, dlaczego to też nie działa? - wiesza LabView...
Właśnie takie zachowanie sugeruje, że funkcja robi coś więcej niż tylko wpisanie danych bezpośrednio pod podany adres - np. próbuje ją zwolnić... albo pisać poza jej obszarem - właśnie zauważyłem - w VI dla funkcji "for Arek" musisz podać na buff zainicjalizowaną tablicę - o żądanej wielkości i wypełnioną wszystko jedno czym.
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

Witam ponownie,

Chwilka przerwy od problemu niestety go nie rozwiązała :-w ...więc wracam do tematu.

Testowałem dziś jeszcze raz obie funkcje.
GrabFrameforArek wywołuję tablicą 1024x768 wypełnioną zerami. Program czasami się wiesza, a czasami przechodzi bez problemu zwracając jakieś śmieci w tablicy wyjściowej (ponowne uruchomienie to te same śmieci,. a ponowne uruchomienie LabVIEW to inne śmieci) - czyli chyba czyta jakiś "nie ten" obszar pamięci.
GrabFrame wywołane w ten sam sposób jak wyżej zwraca tablicę z samymi zerami (lub wartościami, którymi wywołuję - to też sprawdziłem). Nie ma znaczenia czy ustawię na Array Data Pointer czy Array Handle, a nawet Array Handle Pointer.

Co tu jeszcze można zrobić ... zmienić ...?
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

Na tym etapie, to bez kodu funkcji to można tylko pozgadywać. A najlepiej to poproś kolegów, żeby wygenerowali DLL z tymi samymi funkcjami, tylko niezależne od sprzętu - żeby tam był na stałe wrzucony jakiś obrazek (np. goła baba), to pokombinujemy dalej. Nie można przecie odpuścić takiej zniewagi...
Awatar użytkownika
smiga
Administrator
Posty: 800
Rejestracja: 04 paź 2009 12:41
Wersja środowiska: LabVIEW 2016
Lokalizacja: Słupsk

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: smiga »

W tej bibliotece camera.dll funkcja GrabFrameforArek jest niezależna od sprzętu - wypełnia się kolejnymi liczbami od 0 do 255.

U mnie nie działa - czyli zwraca to samo co dostaje na wejściu ... a przy okazji wiesza LabVIEW.

A może kolega, bardzo po koleżeńsku :) , napisze i skompiluje w C (lub czymś innym) bibliotekę z funkcją robiącą to samo, czyli wypełniającą tablicę jakimiś kolejnymi liczbami - zobaczymy czy wtedy u mnie zadziała i co ewentualnie robię źle ... z góry dziękuję :)
Załączniki
camera.rar
(16.78 KiB) Pobrany 438 razy
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

Nie mogę się podłączyć u siebie do tej dll-ki. Wyskakuje, że nie ma vcl100.bpl. Przydałby się też przynajmniej plik nagłówkowy, żeby być na fest pewnym, że dobrze się podłączam.
smiga pisze: A może kolega, bardzo po koleżeńsku :) , napisze i skompiluje w C (lub czymś innym) bibliotekę z funkcją robiącą to samo, czyli wypełniającą tablicę jakimiś kolejnymi liczbami - zobaczymy czy wtedy u mnie zadziała i co ewentualnie robię źle ... z góry dziękuję :)
A zanim coś takiego zmajstruję, to zapytam się nieśmiało, czy ta kamera nie jest przypadkiem kolorowa? Bo jeśli tak to kolega podpina tablicę 3 razy za małą...
vugie
Posty: 383
Rejestracja: 17 lis 2006 00:00
Wersja środowiska: LabVIEW 2009
Lokalizacja: Warszawa

Re: Problem z funkcją pobierania ramek z własnej dll

Post autor: vugie »

Płoszę bałdzo.
Projekt w Dev-C++, skompilowany przy użyciu MinGW, ale dla MSVC nie powinno być specjalnej różnicy.
Chodzi od pierwszego kopa.
Załączniki
genar.zip
(14.27 KiB) Pobrany 443 razy
ODPOWIEDZ