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

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

Post autor: smiga »

Dziękuję bardzo :)
Oczywiście działa.
Powiem więcej, kolega zamienił środek funkcji GrabFrameforfArek tak żeby wypełniała tablicę kolejnymi liczbami od 0 do 255 bez pobierania danych z kamery - też działa bez problemów.

Dlaczego więc z kamerą nie działa nie mam pojęcia. :-\
Siedziałem ostatnio 2h z jednym z kolegów z NI. Jakby uruchomił tą dll'kę, to bym krzyczał z wdzięcznością jego imię, a tak nie wiem czy wypada, więc korzystając z okazji raz jeszcze bardzo dziękuję mu za cierpliwość i chęci :ymapplause: - niestety też nic nie wymyślił.

Być może ta PvAPI.dll (do kamery Prosilica) coś miesza z pamięcią bo Camera.dll korzysta z PvAPI.dll.
Na pewno wskaźnik do tablicy zmienia adres z każdą ramką. Czy to może stwarzać problem?
__ 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 »

Ponawiam pytanie - czy to na pewno czarno-biała kamera?

Chętnie bym mimo wszystko zobaczył kod camera.dll i nagłówki pvapi.dll.
A może w ogóle bezpośrednio przypinać sie do pvapi?
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 »

Tak to czarno-biała kamera ... sorki, przeoczyłem pytanie.

Tak właśnie chodzi mi po głowie podpięcie się bezpośrednio do pvapi.dll. Camera.dll miała mi ułatwić zadanie, bo do tego jest druga biblioteka, napisana przez kolegę, która zajmuje się analizą obrazu.

Kod funkcji GrabFrame oraz GrabFrameforArek z camera.dll poniżej.
Poniższy GrabFrameforArek generuje wspomniane liczby od 0 do 255 sztucznie wypełniając tablicę - ta funkcja działa, ale poprzednia jej wersja (pojedynczy wskaźnik do tablicy wypełnianej przez funkcję, która pobierała te dane z kamery niestety tak samo nie działa jak GrabFrame z podwójnym wskaźnikiem.

int __fastcall TCamera::GrabFrame(UINT8** buff8)
{ // pobierz ramke

// pomiar 'FPS' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if(/*Camera->*/Visible==1){
static int T=30,t=0,count=0;
count++;
if(count>=T)
{ double dt;
dt=(GetTickCount()-t)*1e-3;
LabelFps->Caption=FloatToStrF(T/dt,ffFixed,4,1)+" fps";
t=GetTickCount();
count=0;
}} //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
static int k=0,l;
l=(k+1)%FRAMENUM;
for(int i=0;i<CAMNUM;i++)
{
// czekaj na nowa ramke (gotowa do przetwarzania)
while(1){if(Cam.Frame[l].Context[Acquisition]==(void*)0)break;}
// wskaznik ramki do przetwarzania
buff8=(UINT8*)Cam.Frame[l].ImageBuffer;
// jesli ta ramka nie jest juz zakolejkowana
if((Cam.Frame[k].Context[Acquisition]!=(void*)1))
{ // oznacz ta ramke jako 'zakolejkowana do sciagniecia'
Cam.Frame[k].Context[Acquisition]=(void*)1;
// zakolejkuj ta ramke do sciagniecia
err=PvCaptureQueueFrame(Cam.Handle,&Cam.Frame[k],CameraFrameCB);
PVERROR(err);
}
}
k=(k+1)%FRAMENUM;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
return(err);
}

extern "C" __declspec(dllexport) int __stdcall TCamera_GrabFrame(void* p_, UINT8** buff8)
{
TCamera* p = (TCamera*)p_;
return(p->GrabFrame(buff8));
}

extern "C" __declspec(dllexport) int __stdcall TCamera_GrabFrame_forArek(void* p_, UINT8* buff8_, int H, int W)
{
TCamera* p = (TCamera*)p_;

UINT8* buff8;
int err=p->GrabFrame(&buff8);
for(int i=0;i<(H*W);i++)buff8_=buff8;

//UINT8* buff8[1];
//int err=p->GrabFrame(buff8);
//UINT8* buf=buff8[0];
//for(int i=0;i<(H*W);i++)buff8_=buf[i];

return(err);
}


Odnośnie pvapi.dll - załączam:
Załączniki
prosilica.rar
(352.99 KiB) Pobrany 388 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 »

Zasadniczo TCamera_GrabFrame_forArek wygląda ok, ale robi niebezpieczne założenie, że jest tylko jedna kamera w systemie. Czy sterownik kamery może mieć jakieś przesłanki by podejrzewać, że jest ich więcej?
TCamera_GrabFrame zdecydowanie nie nadaje się do bezpośrdniego użytku. Postaram się z rana dać przykład jak można ją podejść.

Czy któreś ogniwo w łańcuchu nie ma przypadkiem czegoś wspólnego z 64 bitami?
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 »

TCamera_GrabFrame_forArek jest specjalnie napisana z założeniem 1 kamery - bo to dla mnie do testów. Sterownik kamery może "mieć przesłanki by podejrzewać, że jest ich więcej" - funkcja CameraCamInit ma parametr mówiący o liczbie kamer i zwraca numer seryjny kamery oraz rozdzielczość (później jest fukncaja CameraSet Exposure do ustawienia ekspozycji) i nieszczęsna GrabFrame.

"Czy któreś ogniwo w łańcuchu nie ma przypadkiem czegoś wspólnego z 64 bitami?" ... raczej żadne, nic o tym nie wiem, czyli wszystkie 32bitowe
__ 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:TCamera_GrabFrame_forArek jest specjalnie napisana z założeniem 1 kamery ...
Właśnie o to mi chodziło, bo funkcja TCamera::GrabFrame, którą forArek wywołuje takiego założenia już nie robi, a dostaje od forArek miejsce na zapisanie tylko jednego wskaźnika. Więc jeżeli CAMNUM jest większe od 1 następuje nadpisanie pamięci.

Załączam VI wykorzystujący funkcję TCamera_GrabFrame i używający MoveBlock do skopiowania obrazka do obszaru pamięci zaalokowanego przez LV. VI robi założenie że jest 20 kamer i bierze obrazek z pierwszej.
Załączniki
TCamera_GrabFrame.vi
(12.26 KiB) Pobrany 396 razy
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 kolegę Vougie'ego po ponad dwóch tygodniach absencji i przepraszam za ostatni brak czasu - w końcu to w moim interesie ten cały wątek, a ja zawalam :)

Przetestowałem Twój ostatni pomysł.
Efekt jest taki, że na wyjściu TCamera_GrabFrame otrzymuje tablicę jednowymiarową 20 elementów (bo wpisałeś 20 kamer), w której pierwszym elementem jest wskaźnik (za każdym wywołaniem przyjmuje inną wartość, np. 272760836 -czyli wszystko extra), a reszta O, bo mam 1 kamerę. Funkcja MoveBlock bierze więc ten 1 wskaźnik i niestety zwraca same 0 - tablice 1024x768 samych zer.

Zamknąłem jednak fragment Twojego kodu w petlę for i wywołałem ją 10 razy ... i udało się :))
Przy pierwszych 3 wywołaniach kamera chyba nie nadążała się włączyć i zainicjalizować. Dopiero od czwartego razu zbiera odpowiednie dane. Co ciekawe, nawet jak wstawię 1s opóźnienie w pętlę i tak potrzebuje powtórzenia funkcji GrabFrame 4 razy, za każdym razem zwracając oczywiście inny wskaźnik.

Vougie jesteś wielki.
Bardzo dziękuję za pomoc, pełen szacun ... a jeżeli będziesz miał ochotę oderwać się od komputera i zrobisz mi jeszcze jedną uprzejmość, czyli dasz się zaprosić na piwo (lub cokolwiek innego), służę swoim czasem i chętnie się zamelduję w dowolnym miejscu Warszawy (w tym mieście chyba najłatwiej Cię złapać patrząc na Twój profil ? ), celem osobistego poznania genialnego inżyniera. Najbliższą wizytę w Warszawie planuję 22-24.11.2009 (przy okazji szkolenia w NI). Dysponuję więc czasem po godzinie 17 w dniach 22,23,24 ... , ale o szczegółach, jeżeli zrobisz mi ten zaszczyt, najlepiej na priv'a.

Jeszcze raz dziękuję i pozdrawiam ... a swoją drogą fajnie, że jest takie forum, na którym chcą się pojawiać fajni, otwarci, uczynni ludzie z ogromną wiedzą, którą w dodatku chcą się dzielić - chapeau bas!
__ 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 »

Dla formalności pokarzę jak to wygląda:
Obrazek
__ 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:Przy pierwszych 3 wywołaniach kamera chyba nie nadążała się włączyć i zainicjalizować. Dopiero od czwartego razu zbiera odpowiednie dane. Co ciekawe, nawet jak wstawię 1s opóźnienie w pętlę i tak potrzebuje powtórzenia funkcji GrabFrame 4 razy, za każdym razem zwracając oczywiście inny wskaźnik.
No to to już mocno wskazuje na to, że TCamera::GrabFrame jest "nie teges". I nie przypuszczam, by chodziło o czas inicjalizacji, zwłaszcza że mówisz, że to cały czas tak. Przyczyny szukałbym tutaj:

Kod: Zaznacz cały

 static int k=0,l;
l=(k+1)%FRAMENUM;
i tutaj:

Kod: Zaznacz cały

 k=(k+1)%FRAMENUM;
jako, że są to miejsca gdzie się taka cykliczność może pojawić. Ni przypuszczam też żeby API kamery alokowało sobie pamięć na każdą ramkę - jeśli tak, to co każdy czwarty raz wskaźnik zwracany przez TCamera_GrabFrame powinien być taki sam. Chyba że stosowane są jakieś naprzemienne bufory, byłby to wtedy co ósmy raz lub inna wielokrotność.
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 »

To nie jest co czwarty raz. Pierwsze 3 przejścia petli, czyli funkcji GrabFrame zwracają zera. Od 4 dalej już są zwracane wartości (czyli 5,6,7 itd) i za każdym razem wskaźnik jest inny i troszkę inne wartości - i to też dobrze bo tak działa API kamery.
Odnośnie tych pierwszych 3 pustych ramek, kolega powiedział mi dziś, że specjalnie napisał tak funkcję, żeby pierwsze 3 były puste ... ale nie pamięta do czego mu to było potrzebne :) ... czyli on wie, że jest to "nie teges"

Wyświetliłem to dziś funkcją DrawFlattenedPixmap i zastanawiam się czemu jest odwrotność skali - 255 jest czernią, a 0 bielą na rysunku, a w rzeczywistości odwrotnie. Kamera jest też czarno biała, a ja mam dziwne kolory ... ale to pewnie przez tą funkcję wyświetlania - może odwrócę kolory i sprawdzę; dam znać

pozdrawiam
__ 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 »

Odjąłem każdą wartość od 255 i teraz obraz jest OK, czyli czarno-biały do pewnego poziomu ekspozycji (ok 600).
Później wchodzą "dziwne kolory". Co ciekawe w programach pisanych w C++ i Delphi podobną jasność mam przy ekspozycji ok 10000 ...? Podejrzewam, że funkcja DrawFlattenedPicmap stara się zrobić obraz kolorowy z mojego czarno-białego co wnioskuję z wartości - ok 250 (jakoś mała różnica) przy obrazie czarno-białym (ekspozycja 600) i ok 140 (wartość wydaje się normalniejsza) przy "dziwnych kolorach" (ekspozycja 10000), ale nie wiem jeszcze jak to zmienić - może mają koledzy jakieś sugestie?

Jest jeszcze jedna wkurzająca rzecz - dość częste rwanie obrazu (problem z synchronizacją klatek przy wyświetlaniu ? ) - nie występuję w programach pisanych we wspomnianych językach.
__ 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:Odjąłem każdą wartość od 255 i teraz obraz jest OK, czyli czarno-biały do pewnego poziomu ekspozycji (ok 600).
Później wchodzą "dziwne kolory". Co ciekawe w programach pisanych w C++ i Delphi podobną jasność mam przy ekspozycji ok 10000 ...? Podejrzewam, że funkcja DrawFlattenedPicmap stara się zrobić obraz kolorowy z mojego czarno-białego co wnioskuję z wartości - ok 250 (jakoś mała różnica) przy obrazie czarno-białym (ekspozycja 600) i ok 140 (wartość wydaje się normalniejsza) przy "dziwnych kolorach" (ekspozycja 10000), ale nie wiem jeszcze jak to zmienić - może mają koledzy jakieś sugestie?
Bo 8-bitowy obrazek należy poczęstować paletką kolorów, co ilustruje następujący kot:
palet.png
palet.png (10.34 KiB) Przejrzano 17457 razy
Jest jeszcze jedna wkurzająca rzecz - dość częste rwanie obrazu (problem z synchronizacją klatek przy wyświetlaniu ? ) - nie występuję w programach pisanych we wspomnianych językach.
A to już przypadłość kontrolki Picture. Tutaj i tutaj garść informacji jak sobie radzić z różnymi jej chimerami. Podsumowując warto najpierw zaznaczyć "Erase first".
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 »

Wielkie dzieki - znowu genialne rozwiazanie Kolegi Vugie :ymapplause:

Co ciekawe pozwolilo mi to wyeliminowac koniecznosc odejmowania kazdego bajtu od 255.
Nie do konca rozumiem jednak jak to dziala - podaje na wejcie "colors" tablice 255 elementow od 0 do 255 osiagajac ... cel ... , ale dziala :)
__ 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 »

Działa to tak, ponieważ obrazek 8-bitowy nie jest interpretowany domyślnie jako skala szarości, tylko jako tak zwany kolor "indeksowany" - wartość piksela nie określa jasności, tylko "numer koloru" - indeks w tablicy kolorów (palacie), pod którym jest przechowywany właściwy kolor. Jeżeli nie zdefiniuje się palety (pole Colors) LabVIEW używa swojej domyślnej.
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 »

Znalazłem ładny opis, a przy okazji drugi możliwy sposób rozwiązania ćwiczonego w wątku problemu ... więc wrzucam link:
http://decibel.ni.com/content/docs/DOC-9091
__ Arkadiusz Śmigielski, tel. 662 01 01 74___
ObrazekObrazekObrazek
ODPOWIEDZ