Losowe wybieranie WSZYSTKICH pikseli obrazka

0

Cześć.

Zastanawiam się jak stworzyć algorytm, który z obrazka w PictureBox'ie, załóżmy 10x10 powybiera wszystkie piksele tak, żeby np. potem je namalować SetPixelem na nowo (to tylko przykład, w założeniu ma dziać się coś innego, ale nie chcę tego teraz tłumaczyć) ale żeby robił to losowo, a nie od piksela (0,0) do piksela (9,9). Oczywistą sprawą jest to, że program musi zapamiętać, że każdy piksel został już wybrany. Złożoność algorytmu nie ma znaczenia, byle by działało!

Macie jakiś pomysł? Stawiam forumowe "piwa" :D

2

Jako, że już wpadłem na odpowiedź, sam sobie jej udzielę na forum :P

W uproszczeniu w kodzie:


int pikseli = wysokosc*szerokosc;
bool sprawdzone[wysokosc][szerokosc] //... (tablica wypełniona false'ami)
int losowa1, losowa2;

bool moge_przejsc_dalej;

for (int i=0; i< pikseli; i++)
{
    moge_przejsc_dalej=false;
    while(moge_przejsc_dalej==false)
    {
        losuj losowa1 z zakresu [0-wysokość]
        losuj losowa2 z zakresu [0-szerokość]
	    
		if(sprawdzone[losowa1][losowa2]==false)
		{
			obrazek.SetPixel(losowa1,losowa2,Color.Green); - przykładowa operacja
			sprawdzone[losowa1][losowa2] = true;
			moge_przejsc_dalej = true;
	    }
		
    }
}

Zamysł stworzenia zmiennej moge_przejsc_dalej był taki, że gdy wylosujemy piksel ktory był już sprawdzany, program nie pozwoli przejść do kolejnego przebiegu pętli, więc mamy gwarancję, że w sumie 100 pikseli zostanie sprawdzonych :) Wydaje mi się, że to łatwe, ale proszę o zweryfikowanie czy widzicie jakąś nieprawidłowość

0

To kod wymieszany ze zwykłym językiem. Jesteśmy w dziale algorytmy, a poza tym napisałem "w uproszczeniu". Zwracanie mi uwagi na błędy syntaktyczne jest chyba nie na miejscu...

2

A ja bym powiedział, że nie jest to dobry pomysł. Mając obrazek 10x10px, prawdopodobnieństwo wybrania tego ostatniego pixela to 1/100. Inaczej mówiąc im dalej, ten algorytm będzie działał wolniej. Zrób sobie listę (np vector) wpakuj tam obiekty ze wspólrzędnymi X i Y każdego pixela. Przy 10x10 na takiej liscie będzie 100 elementów. Następnie Wykonujesz tylko 100 losowań, za każdym razem losując z zakresu [0, lista.size] a po wylosowaniu usuwając z listy. Nie ma wtedy sytuacji, że wylosujesz 2x ten sam pixel.

 
List<Tuple<int, int>> pixels = new List<Tuple<int, int>>();
for(x=0; x<picturebox.width; ++x)
{
for(y=0; y<picturebox.height; ++y)
{
 pixels.Add(new Tuple<int, int>(x, y));
}
}

Randrom rand = new Random();
for(i=0; i<picturebox.width*picturebox.height; ++i)
{
 Tuple<int, int> pixel = pixels[rand.Next(pixels.Length)];
 pixels.remove(pixel);
//tutaj pod pixel masz parę liczb Item1 - x i Item2 - y  wylosowanego pisela.
}

0
misiakufal napisał(a):

A ja bym powiedział, że nie jest to dobry pomysł. Mając obrazek 10x10px, prawdopodobnieństwo wybrania tego ostatniego pixela to 1/100. Inaczej mówiąc im dalej, ten algorytm będzie działał wolniej. Zrób sobie listę (np vector) wpakuj tam obiekty ze wspólrzędnymi X i Y każdego pixela. Przy 10x10 na takiej liscie będzie 100 elementów. Następnie Wykonujesz tylko 100 losowań, za każdym razem losując z zakresu [0, lista.size] a po wylosowaniu usuwając z listy. Nie ma wtedy sytuacji, że wylosujesz 2x ten sam pixel.

Masz racje, złożonośc obliczeniowa przy większym obrazku byłaby tak duża, że nie byłoby sensu odpalać programu :) Dobry pomysł, zaraz spróbuję zaimplementować to w kodzie.

Dzięki

1

troche zbombardowany jestem ale z tego co widze to:

  1. liczysz ilosc wszystkich pikseli (szerokosc razy wysokosc)
  2. tworzysz tablice od zera do ilosci wszystkich pikseli -1 z wartosciami typu Point (X, Y dla danego piksela)
  3. z dlugosci tej tablicy losujesz liczbę - bedzie miala ona parametry X i Y jeszcze nie przerobionego piksela
  4. usuwasz z tablicy wylosowany element - dlugosc tablicy zmniejsza się o jeden
  5. jezeli dlugosc tablicy jest rowna zero to zakoncz algorytm, inaczej wróc do punktu 3

Pozdrawiam,
Patryk

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