Jak wpisac bitmape do ramu...

0

Witam

Mam taki problem, potrzebuje procedure do Delphi, ktora pomoze mi zapisac dowolna bitmape w pamieci RAM komputera, a nastepnie pozwoli na wykonanie podstawowych operacji, takich jak: binaryzacja, segmentacja, indeksacji itp...

Bardzo bym prosil o podanie przykladu, jak zapisac ja do Ramu i jak odwolac sie do niej...

Dzieki

0

Wczytujesz w taki sposób:

var
  bitmapa: TBitmap;
begin
  bitmapa:= TBitmap.Create;
  bitmapa.LoadFromFile('c:\obraz.bmp');
end;

Referencje do składowych obrazka uzyskujesz przez wywołanie funkcji ScanLine()

Oto procedura na progowanie (domyślam, że to miałeś na myśli pisząc binaryzacja, segmentacja):

procedure Threshold( Bitmap:TBitmap ; const Light:TRgbTriple; const Dark:TRgbTriple; Amount:Integer = 128);
var
Row:^TRGBTriple;
H,V,Index:Integer;
begin
 Bitmap.PixelFormat:=pf24bit;
 for V:=0 to Bitmap.Height-1 do
  begin
    Row:=Bitmap.ScanLine[V];
    for H:=0 to Bitmap.Width -1 do
    begin
    Index := ((Row.rgbtRed * 77 +
       Row.rgbtGreen* 150 +
       Row.rgbtBlue * 29) shr 8);
       if Index>Amount then
      Row^:=Light  else Row^:=Dark ;
       inc(Row);
    end;
  end;
end;
0

Dzieki, za szybka odpowiedz, tak szybka ze dopiero sie kapnalem dzisiaj ze jest :)

Tak mniej wiecej oto mi chodzilo, a dokladniej czy mozesz mi powiedziec, czy ScanLine to bedzie to samo co w canvas Pixels[j,i] ??

A ewnetulanie gdzie moge o tym szukac ?

pozdrawiam

0

Po pierwsze ScanLine będzie o niebo szybsze. Po drugie nie będzie do końca tym samym: jeśli bitmapa jest powiedzmy 16 bitowa, piksel wskazywany przez ScanLine będzie miał 2 bajty, a Pixels mimo wszystko będzie pokazywał wszystkie składowe RGB i dbał o ich dekompozycję z powrotem na 16 bitów.

Zatem: ScanLine zwraca dokładnie adres linii pikselków w pamięci, a jej kolejne elementy o rozmiarze takim jak przestrzeń kolorów bitmapy to kolejne piksele, a Pixels zwraca odwołania do pikseli o współrzędnych X,Y, konwertując przez RGB.

0

Dzięki ScanLine otrzymujesz wskaźnik do początku linii bitmapy dzięki czemu dostęp do poszczególnych pikseli jest szybszy niż do każdego piksela z osobna (przez Pixels) i to jest właśnie ta różnica. Zdecydowanie lepiej i szybciej będzie dzięki ScanLine i właśnie tego powinieneś używać. Troszkę o ScanLine jest w serwisie poza tym jest co nieco tutaj: http://www.efg2.com/Lab/ImageProcessing/Scanline.htm

/dopisane: Szczawik napisał bardzo istotną rzecz. Przed użyciem ScanLine musisz wiedzieć jaki jest lub samemu nadać PixelFormat inaczej nie będziesz wiedział jakiej wielkości są poszczególne piksele.

0

Dzieki koledzy za szybka odpowiedz. Troche mi to rozjasnilo umysl...

Ale mam jeszcze jedno pytanie (nie wiem czy ostatnie ;))
Jezeli juz zrobie to zmiane na bitmapie w ramie, to czy jezeli bede ja przetwarzal jeszcze raz, nie zapisujac jej wczesniej na dysk, to czy zmiany te zostana wprowadzone do pamieci i czy bede pozniej mogl juz na gotowo zapisac bitmape z RAM-u??

Moze napisze jasniej. Dostaje obraz z kamerki internetowej, jedna ramke, zdjecie, nastepnie musze ten obraz zbinaryzowac, nastepnie odszumic, zlokalizowac i policzyc elementy na obrazie (proste ksztalty:trojkat, prostokat, kolo, kwadrat), a nastepnie podobne obiekty zaznaczyc jednym kolorem i wyswietlic...

Czy cos takiego jak opisalem powyzej, jestem w stanie zrobic na tej bitmapie zapisanej w pamieci? czy jednak musze to zapisywac jakos i odtwarzac?

Pozdrawiam i dzieki za zainteresowanie...

0

Tak wszystko możesz zrobić na tej bitmapie znajdującej się w pamięci. Możesz również wyświetlić ją na ekranie po dokonaniu operacji np. za pomocą komponentu TImage bez konieczności zapisywania na dysk.

0

Ok, to bardzo fajnie :)

Mam jeszcze jedno pytanie...

Jak pobrac wartosc pixela i jednoczesnie pobrac wartości pixeli poprzednich za pomoca ScanLine?

Chodzi mi o to ze np chce pobrac pixel[x,y] oraz wartosci pixeli [x-1,y-1] [x,y-1] [x+1,y-1] [x-1,y]... bo wlasnie na podstawie takiej maski moge wykryc ilosc przedmiotow na obrazie. Za pomoca Pixels[x,y] jest prosto, ale bardzo wolno, jak to bedzie z ScanLine?

Pozdrawiam

0

Zrób 3 razy ScanLine dla każdej badanej linii:

coś takiego:

var
  TL,TC,TR,BL,BC,BR,LL,LC,LR:^TRGBTriple;
begin
  for V := 1 to Bitmap.Height - 2 do
  begin
    TL:= Bitmap.ScanLine[V - 1];
    TC:=TL;
    TR:=TL;
    BL:= Bitmap.ScanLine[V];
    BC:=BL;
    BR:=BL;
    LL:= Bitmap.ScanLine[V + 1];
    LC:=LL;
    LR:=LL;
    inc(TC); inc(TR,2);
    inc(BC); inc(BR,2);
    inc(LC); inc(LR,2);

W ten sposób masz 9 pikseli w sam raz do obróbki filtrem konwolucyjnym:
TL TC TR
BL BC BR
LL LC LR

Tu jest cały kodzik na blur z naszego serwisu:

Procedure Blur( var Bitmap :TBitmap);
var
TL,TC,TR,BL,BC,BR,LL,LC,LR:^TRGBTriple;
H,V:Integer;
begin
Bitmap.PixelFormat :=pf24bit;
for V := 1 to Bitmap.Height - 2 do
begin
TL:= Bitmap.ScanLine[V - 1];
TC:=TL;    // to samo Scanline  Bitmap.ScanLine[V - 1]; tylko oszczędniej
TR:=TL;
BL:= Bitmap.ScanLine[V];
BC:=BL;
BR:=BL;
LL:= Bitmap.ScanLine[V + 1];
LC:=LL;
LR:=LL;
inc(TC); inc(TR,2);
inc(BC); inc(BR,2);
inc(LC); inc(LR,2);

for H := 1 to (Bitmap.Width  - 2) do
begin
//Wyciągam srednią z 9 sąsiadujących pixeli
  BC.rgbtRed:= (BC.rgbtRed+ BL.rgbtRed+BR.rgbtRed+
  TC.rgbtRed+ TL.rgbtRed+TR.rgbtRed+
  LL.rgbtRed+ LC.rgbtRed+LR.rgbtRed) div 9 ;

  BC.rgbtGreen:=( BC.rgbtGreen+ BL.rgbtGreen+BR.rgbtGreen+
  TC.rgbtGreen+ TL.rgbtGreen+TR.rgbtGreen+
  LL.rgbtGreen+ LC.rgbtGreen+LR.rgbtGreen) div 9 ;

  BC.rgbtBlue:=( BC.rgbtBlue+ BL.rgbtBlue+BR.rgbtBlue+
  TC.rgbtBlue+ TL.rgbtBlue+TR.rgbtBlue+
  LL.rgbtBlue+ LC.rgbtBlue+LR.rgbtBlue )div 9 ;
//zwiększam wskaźniki biorąc następne 9 pixeli
  inc(TL);inc(TC);inc(TR);
  inc(BL);inc(BC);inc(BR);
  inc(LL);inc(LC);inc(LR);
    end;
  end;
end;
0

Dzieki :) bawie sie tym wlasnie i dalej mam problem...

Dlaczego w kodzie na poczatku podlaes tylko:

inc(TC); inc(TR,2);
    inc(BC); inc(BR,2);
    inc(LC); inc(LR,2);

a pozniej :

  inc(TL);inc(TC);inc(TR);
  inc(BL);inc(BC);inc(BR);
  inc(LL);inc(LC);inc(LR);

Bo tej rzeczy nie rozumiem...

I jeszcze jedno piszac to:

TL:= Bitmap.ScanLine[V - 1];
TC:=TL;    // to samo Scanline  Bitmap.ScanLine[V - 1]; tylko oszczędniej
TR:=TL;
BL:= Bitmap.ScanLine[V];
BC:=BL;
BR:=BL;
LL:= Bitmap.ScanLine[V + 1];
LC:=LL;
LR:=LL;

oznacza to ze on skanuje kolejne pixele TL,TC,TR w poziomie tak?
i to sa 3 pierwsze pixele bitmapy z zerowego rzedu? dobrze to rozumiem ?

Pozdrawiam

0

oznacza to ze on skanuje kolejne pixele TL,TC,TR w poziomie tak?
i to sa 3 pierwsze pixele bitmapy z zerowego rzedu? dobrze to rozumiem ?

Tak dobrze to rozumiesz.

Nie ja to pisałem, więc nie do mnie pretensje, że nie jest zbyt jasno zapisane :P

Ten fragment:

TL:= Bitmap.ScanLine[V - 1];
TC:=TL;    // to samo Scanline  Bitmap.ScanLine[V - 1]; tylko oszczędniej
TR:=TL;

oraz ten fragment:

inc(TC); inc(TR,2);

stanowią całość. TL to pierwszy piksel pierwszej linii, do TC oraz TR wczytujemy piksel TL (czyli pierwszy piksel), a następnie przesuwamy się TC o jeden do przodu (inc(TC)), a TR przesuwamy się o dwa do przodu (inc(TR,2)). Dzięki temu mamy w tych zmiennych kolejno TL (pierwszy piksel), TC (drugi piksel), TR (trzeci piksel).

Natomiast ten fragment:

  inc(TL);inc(TC);inc(TR);
  inc(BL);inc(BC);inc(BR);
  inc(LL);inc(LC);inc(LR);

Sprawia, że przesuwamy naszą matrycę 3x3 do przodu o jeden piksel.

Filtr konwolucyjny to taka matryca 3x3 (może mieć inny rozmiar oczywiście) chodząca po całym obrazku i ustalająca wartość piksela, który jest w środku na podstawie wartości otaczających go pikseli przemnożonych przez wartość zapisaną w tej matrycy.

Tutaj masz trochę teorii: http://anisko.net/agent501/segmentacja/DetekcjaKrawedzi/

0
AdamPL napisał(a)

... TL to pierwszy piksel pierwszej linii, do TC oraz TR wczytujemy piksel TL (czyli pierwszy piksel), a następnie przesuwamy się TC o jeden do przodu (inc(TC)), a TR przesuwamy się o dwa do przodu (inc(TR,2)). Dzięki temu mamy w tych zmiennych kolejno TL (pierwszy piksel), TC (drugi piksel), TR (trzeci piksel).

Dzieki wielkie własnie o takie wyjaśnienie mi chodzilo:) zaraz sie za to zabieram :)

Pozdrawiam

Pewnie jeszcze tu bede pisal :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1