Analiza obrazu w C#

0

Witam :p

Mam takiego sympatycznego jamnika:
darmowy hosting obrazków

Chciałbym pobawić się w zmianę kontrastu tego obrazu, stworzenie histogramu i tym podobne rzeczy. Mam w głowie pomysł jak to ma działać:
Mianowicie, cały obraz chciałbym potraktować jako macierz piksli. A w tym przypadku piksel to po prostu liczba z przedziału od 0 do 255. Czyli pierwszą rzeczą jaką musiałbym zrobić to wczytać obraz z dysku i zamienić go na macierz- zwykłą tablice dwuwymiarową. Druga rzecz: stworzył bym dwie pętle for. Jedna przebiegałaby jamnika w wierszach, a druga w kolumnach. W ciele pętli napisałbym polecenie którego sens brzmi następująco: "zamień piksel na liczbę z przedziału od 0 do 255, i wstaw do macierzy, którą stworzyliśmy na początku". Potem stworzyłbym odpowiednie funkcje zmieniające jasność wejściową na jakąś nową.
I2 =F(I1 )

Tyle teorii. Domyślam się, że brzmi to bardzo nieprofesjonalnie, ale chciałem wytłumaczyć co chcę zrobić. Oto moje pytania:
-Jak zamienić obraz na tablicę piksli? Jakie metody stworzone do tego celu oferuje C#? Jakich bibliotek użyć?
-Jak zamienić piksel na liczbę? Jakie metody stworzone do tego celu oferuje C#? Jakich bibliotek użyć?
-Jak z tablicy (macierzy) liczb, wrócić z powrotem do obrazu?

Pozdrawiam i dziękuję z góry za wszelką pomoc ;)

0

Jak zamienić obraz na tablicę piksli?

po co? obraz = bitmapa czyli dosłownie mapa pikseli. Dostęp do pojedyńczych pikseli masz przez funkcję GetPixel(int x, int y)

A w tym przypadku piksel to po prostu liczba z przedziału od 0 do 255

to 4 liczby. ARGB.

0

A jakich bibliotek potrzeba, aby skorzystać z tej funkcji? Mógłbyś pokazać na przykładzie jak jej dokładnie użyć?

0

Tak trudno wpisać w gooogle "getpixel c#"?
http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx

Edit: i w ogóle poczytaj sobie o ColorMatrix

1

Podsuwacie GetPixel, a potem będzie pytanie dlaczego jest tak wolno.
Trzeba od razu użyć Bitmap.LockBits i odwoływać do pamięci przez wskaźnik — bez użycia GetPixel.
Przykładów jest dużo, tu na tym forum również.

1

Przede wszystkim trzeba skorzystać ze wskaźnika. Poczytaj więc o unsafe. Dodatkowo trzeba odpowiednio ustawić sobie środowisko bo standardowo Visual Studio nie zezwala na wykorzystanie "niebezpiecznego kodu".

Następny krok to poczytanie o PixelFormat. Chociaż nazwa mówi sama za siebie o co chodzi.

Aby filtracja przebiegała w miarę szybko należy zablokować bmp w pamięci. Używamy do tego celu LockBits.
Później robimy coś co jest podobne do ScanLine z C++ Buildera, czyli Scan0. To jest deklaracja wskaźników na początek tablic danych w pamięci.

Nie można też zapmnieć o zwolnieniu pamięci poprzez UnlockBits.

Pogrubione elementy są zaznaczone specjalnie. To te słowa powinieneś wpisać w google i zacząć czytać i czytać i czytać :)
Nic więcej nie trzeba do napisania tego co chcesz.

1

Trzeba skorzystać ze wskaźnika (w pewnym momencie tylko), ale nie trzeba z unsafe. Czasem wręcz nie można. LockBits zwraca nam IntPtr, który możemy podać do Marshall.Copy i skopiować sobie wszystko do zwykłej tablicy bajtów. Z jednej strony tracimy czas i pamięć na kopiowanie obrazu w jedną (i w drugą stronę, jeśli chcesz), ale jest to stosunkowo mały narzut. Aleksander Polak na forum codeguru.pl swojego czasu przeprowadził coś dogłębne testy, ale nie mogę znaleźć teraz tego wątku (też mają świetnie działają wyszukiwarkę).
edit: ok, pomogło google: http://www.codeguru.pl/forum/watek/szybsza-grafika-w-systemdrawing,484903

0

Też można, chociaż jak dla mnie metoda z unsafe jest prostsza niż z Marshal.Copy ;-)
A jakby nam naprawdę zależało na wydajności, to DLL-ka w C++ i użycie instrukcji SIMD. Kilka razy szybciej niż unsafe w C#.
Ale dla takiego jamniczka to już byłaby przesada.

0

Co do wszelkich zmian kolorów można użyć wspomnianą ColorMatrix

http://msdn.microsoft.com/en-us/library/a7xw19wh.aspx (Recoloring Images)

Tu nie ma problemu z "powolnym GetPixel".

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