Blog (76)
Komentarze (5.6k)
Recenzje (0)
@nintyfanProsta aplikacja do „kolażu” zdjęć

Prosta aplikacja do „kolażu” zdjęć

Jako iż  leniwość matką wynalazku, to zamiast szukać programu, który pasowałby gustom mego znajomego, wolałem sam taki program napisać. Do pracy zaprzągłem OpenCV i gdyby nie to, że brakowało mi jednej rzeczy, to program do kolażu zdjęć napisałbym w miarę szybko. Zacząłem niestety chyba od podsumowania... Czas prześledzić od początku.

Kolaż zdjęć

Kolaż zdjęć, to umieszczenie zdjęć każdego z wybranych obok innego wybranego. Z tego powstaje duży obraz.

Właściwy wstęp

OpenCV dostarcza bardzo wiele możliwości. posłużę się możliwością odczytu obrazów, a także ich skalowania. Wykorzystam także bibliotekę Libgreattao, jednak w tym wpisie pominę rzeczy związane z tą biblioteką. Jutro wrzucę też gdzie źródła mojego programu, zwanego kola.

[h2']Założenia[/h2]

W moim wypadku postanowiłem, by zdjęcia miały identyczne wymiary, więc muszą zostać przeskalowane. Jednak, by nie tracić za bardzo na jakości, to obliczymy średnią szerokość zdjęcia i średni stosunek wysokości i szerokości. Zdjęcia zostaną przeskalowane do średnia szerokość w ramach szerokości i średnia szerokość * stosunek w ramach wysokości. Wyciągniemy także pierwiastek drugiego stopnia z liczby zdjęć, by znać ilość zdjęć w wierszu. Podłoga tego pierwiastka, to będzie ilość zdjęć w wierszu, więc dla trzech zdjęć otrzymamy 1, a dla czterech 2.

Należy zwrócić uwagę na jeden aspekt. Jeżeli podzielimy ilość zdjęć przez otrzymaną podłogę, by uzyskać liczbę wierszy, to możemy otrzymać błędny wynik. Z tego względu należy wykonać pewne sprawdzenie

[code=C] floor((float) count / in_row) == (float)count / in_row [/code]

Sprawdzamy czy zostaje reszta z dzielenia, a jeżeli tak, to do ilości wierszy dodajemy jeden. By korzystać z możliwości poszerzania obrazka, to musimy zdefiniować obrazek z docelowymi wymiarami, a następnie wywołać odpowiednio funkcję cvResize. Na początku wpisu wspomniałem, że była pewna niedogodność. Chodziło o to, że nie potrafiłem znaleźć funkcji, która kopiowałaby dane z przesunięciem. Z tego względu musiałem sam zaimplementować tę cechę programu.

Kawałki kodu

Obrazek wczytujemy w następujący sposób:

[code=C] obrazek = cvLoadImage(ścieżka, CV_LOAD_IMAGE_COLOR); [/code]

Za ścieżka należy podstawić ścieżkę do obrazka. Oczywiście, że funkcja zwraca wskaźnik do odpowiedniej struktury.

Ważnym etapem jest zbieranie statystyk co do naszych obrazków. Oto kod:


   ++count;
    img_width = image->width;
    img_height= fimage->height;
    avg_proportion += (float) img_width / (float) img_height;
    avg_width += img_width;

Powyższy kod należy umieścić w pętli wczytującej obrazki. Myślę, że nie trzeba go tłumaczyć.

Poniżej pętli należy umieścić poniższy kod:

[code=C] avg_proportion /= count; avg_width /= count;

in_row = (int) sqrt(count); if (floor((float) count / in_row) == (float)count / in_row) { resultImage = cvCreateImage(cvSize((int)(in_row * avg_width), (int)(avg_width * avg_proportion * count / in_row)), f_dialog.files->image->depth, f_dialog.files->image->nChannels); } else { resultImage = cvCreateImage(cvSize((int)(in_row * avg_width), (int)(avg_width * avg_proportion * (count / in_row + 1))), f_dialog.files->image->depth, f_dialog.files->image->nChannels); } resizeImage = cvCreateImage(cvSize((int)(avg_width), (int)(avg_width * avg_proportion)), f_dialog.files->image->depth, f_dialog.files->image->nChannels); cvSetZero(resultImage); cvSetZero(resizeImage);

[/code]

Ważna jest funkcja cvCreateImage. Pierwszym argumentem jest struktura zawierająca wymiary naszego obrazka. Szerokością będzie ilość obrazków w wierszu pomnożona przez średnią szerokość obrazka. Wysokością będzie średnia szerokość pomnożona przez stosunek i dodatkowo pomnożone przez iloraz ilości obrazków i ilości obrazków w wierszu. Tutaj stosujemy sztuczkę z dodaniem dodatkowo wiersza,, zwiększając wspomniany iloraz o jeden. cvSetZero wypełnia obrazki czernią, ale w drugim wypadku jest to raczej zbędne.

Następnie należy łączyć obrazki. Musimy pamiętać zmienne i (ilość obrazków położonych w bieżącym wierszu), x (przesunięcie względem lewej krawędzi), y(przesunięcie względem górnej krawędzi). Jeżeli i osiągnie in_row, to musimy wyzerować x, wyzerować i, a także do y dodać średnią wysokość obrazka.

W pętli łączącej obrazki należy kopiować piksele z obrazka rozszerzonego do ostatecznego. Należy pamiętać, że:

  1. Obrazek ma image->width szerokości i image->height wysokości
  2. Jednak to nie wystarcza, bo szerokość należy mnożyć przez liczbę kanałów, czyli bps

Ostatecznie zapisujemy obrazek funkcją cvSaveImage, jak poniżej:

[code=C] cvSaveImage(ścieżka, obrazek_do_zapisu, 0); [/code]

To już wszystko na dzisiaj!

Wybrane dla Ciebie

Komentarze (3)