Zliczanie zmian koloru pixelka JAK???

0

Temat jest taki:
mam do dyspozycji Delphi (3 i 6) mało czasu i dużo bitmap do obrobienia.

Zagadnienie wygląda tak:
4x 3000 plików bmp. ponumerowanych od 0000.bmp - 2999.bmp (niektóre projekty mają więcej plików). Pliki są tak jakby filmem z kamery przemysłowej, obrobionym w pewnym programie. W zależności od pewnych warunków do filmu zostało dorysowane 8 pół (kwadracików) które zmieniają kolory FFFFFF - 000000 - FFFFFF - 000000 itd (tylko 2 możliwości). Kwadraciki te są zawsze w tym samym miejscu. Temat polega na tym że mam policzyć ile razy każdy z tych kwadracików miał kolor np. biały (FFFFFF). JAK?

Wymyśłiłem sobie że będzie to program który otwiera po kolei każdy plik i sprawdza kolor pixelków o współrzędnych X1, Y1, X2, Y2, ..., X8, Y8 a na końcu przedstawia wynik (liczbę wystapień).

Proszę o podpowiedź: jakie komponenty (najlepiej standardowe), jakieś algorytmy, fragmenty kodu itd :)

Z góry dzięki :-O

0

Najszybciej (w znaczeniu napisania kodu) jest otwierać pliczki bmp w TBitmap z modułu Graphics i wykożystać coś takiego (Bit as TBitmap).Canvas.Pixels[x, y] ta konstrukcja zwraca kolor pixela o wsp. x, y. Ale jeżeli o szybkość to niestety nie mam dobrych wiadomości może to trochę potrwać.
Pozdrawiam

0

Albo Można Liczyć ScanLine'm
do procedury podajesz Bitmapę i Liczniki - czarnego(Black) i białego - White
Liczniki nie są zerowane ich wartości wzrastają

procedure CheckBitmap( Bitmap:TBitmap;  var Black,White:Integer);
 type
 P=array [0..2048] of TRGBTriple; // przyjmuje że max szerokości bitmapy to 2048 pixeli
var
Px1:^P;
H,V:Integer;
begin
Bitmap.PixelFormat:=pf24Bit; // Jeśli bitmapy są 24bitowe to ta linia jest niepotrzebna , jeśli nie to bitmapa  musi być przekonwertowana na 24 bity

Px1:=Bitmap.ScanLine [5];// Pozycja Y   //Podajesz pozycje Y interesującego cie pixela
if (Px1[10].rgbtBlue=0) then inc (Black) else inc(White); //Pozycja X interesującego pixela

//W tym przypadku zostanie sprawdzony pixel [10,5] jeśli nie zmieniasz Linii to możesz powtórzyc
if (Px1[20].rgbtBlue=0) then inc (Black) else inc(White); //Pozycja X interesującego pixela , tym razem [20,5]

//Jeśli natomiast zm,mieniasz Linię to 
Px1:=Bitmap.ScanLine [18];// Pozycja Y   //Podajesz pozycje Y interesującego cie pixela
no i znowu sprawdzasz 
if (Px1[20].rgbtBlue=0) then inc (Black) else inc(White); //Pozycja X interesującego pixela , tym razem [20,18];

{Przygotuj sobie w ten sposób wszystkie pixele do sprawdzenia}



end;

To powinno być dużo szybsze od Canvas[X,Y]
aha jeszcze jedno

if (Px1[20].rgbtBlue=0) then inc (Black) else inc(White);

ten zapis oznacza ze sprawdzasz wartość niebieskiego w pixelu 20 w danej linii
Wystarczy tylko sprawdzić składową niebieską bo czarny to R=0 G=0 B=0 a biały to R=255 G-255 B=255
inc(Black) oznacza tyle saamo co Black:=Black+1;

0

wielkie dzięki za odpowiedź, nie spodziewałem się tak szybko, nie spodziewałem się w ogóle! ;) w weekend postaram sie wypróbować i powiem jak się to sprawdzi

ps moje bmp są w szarościach (256 odcieni)

0

A ja mam inną propozycję - o wiele szybszą: skoro to bitmapy z kamery przemysłowej to zapewne mają stały - określony format. To oznacza, że zmieniane bity są zawsze w tym samym miejscu pliku (Możesz to sprawdzić choćby jakimś hex-edytorem). Możesz więc je odczytać tak:

////////////////////////////////////////////////////////////////////////////////
//N - liczba znajdująca się w nazwie pliku (n.bmp).
//Piksel - przy powodzeniu wykonania funkcji zawiera wartość wskazanego piksela,
//       - przy niepowodzeniu wykonania funkcji zawiera wartość nieokreśloną.
//
//result - zwraca informację o poprawności wykonania odczytu z pliku
////////////////////////////////////////////////////////////////////////////////

type TPiksel = byte;  //Bitmapa w skali szarości

function GetPixelFromFile(const N:integer; var Piksel:TPiksel):boolean;
const Offset = $00008000; //Ustalona pozycja piksela
var BmpHandle:THandle;
    Read:DWORD;
begin
result:=FALSE;
BmpHandle:=CreateFile(PChar(IntToStr(N)+'.bmp'), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (BmpHandle<>INVALID_HANDLE_VALUE) then
  begin
  if (SetFilePointer(BmpHandle, Offset, nil, FILE_BEGIN)<>$FFFFFFFF)
    and ReadFile(BmpHandle, Piksel, sizeof(Piksel), Read, nil)
    and (Read=sizeof(Piksel)) then
    result:=TRUE;
  CloseHandle(BmpHandle);
  end;
end;

Nie ma chyba szybszej i mniej pamięciożernej funkcji do tego zadania.

//Dopisane - pamiętaj, że pliki w skali szarości są oparte na palecie, umieszczonej na początku pliku. Jeśli ona też może się zmieniać, najpierw z niej odczytaj, jakie indeksy odpowiadają szukanym kolorom.

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