Strona 2 z 3
Re: Problem z funkcją pobierania ramek z własnej dll
: 25 paź 2009 02:54
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

- 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?
Problem z funkcją pobierania ramek z własnej dll
: 25 paź 2009 19:55
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?
Re: Problem z funkcją pobierania ramek z własnej dll
: 25 paź 2009 20:43
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:
Problem z funkcją pobierania ramek z własnej dll
: 25 paź 2009 23:32
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?
Re: Problem z funkcją pobierania ramek z własnej dll
: 27 paź 2009 23:56
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
Re: Problem z funkcją pobierania ramek z własnej dll
: 28 paź 2009 10:37
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.
Re: Problem z funkcją pobierania ramek z własnej dll
: 15 lis 2009 22:23
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!
Re: Problem z funkcją pobierania ramek z własnej dll
: 15 lis 2009 22:43
autor: smiga
Dla formalności pokarzę jak to wygląda:

Re: Problem z funkcją pobierania ramek z własnej dll
: 16 lis 2009 09:55
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:
i tutaj:
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ść.
Re: Problem z funkcją pobierania ramek z własnej dll
: 16 lis 2009 17:53
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
Re: Problem z funkcją pobierania ramek z własnej dll
: 21 lis 2009 21:46
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.
Re: Problem z funkcją pobierania ramek z własnej dll
: 23 lis 2009 10:14
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 (10.34 KiB) Przejrzano 22721 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".
Re: Problem z funkcją pobierania ramek z własnej dll
: 24 lis 2009 12:14
autor: smiga
Wielkie dzieki - znowu genialne rozwiazanie Kolegi Vugie
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

Problem z funkcją pobierania ramek z własnej dll
: 24 lis 2009 12:56
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.
Re: Problem z funkcją pobierania ramek z własnej dll
: 01 lis 2011 23:43
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