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

Prosta aplikacja do „kolażu” zdjęć

16.11.2015 21:05, aktualizacja: 18.11.2015 11:26

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)