czwartek, 24 marca 2011

Wygodna konfiguracja procesu budowania programów OpenCV w CMake

0 komentarze
O sposobach kompilacji programów OpenCV w Linuksie pisałem ostatnio we wpisie OpenCV - instalacja i pierwszy przykład w Ubuntu. Pokazalem tam również przykladowy plik konfiguracyjny dla CMake: CMakeLists.txt. Na pierwszy rzut oka wydaje się on w porządku, jednakże jeśli zacznie nam przybywać nowych programów, wówczas kopiowanie tych dwóch linijek rozpoczynających się od ADD_EXECUTABLETARGET_LINK_LIBRARIES może być irytujące. Można oczywiście sobie z tym poradzić i przekonać CMake d bardziej zautomatyzowanej pracy - przykład poniżej:

PROJECT(NazwaProjektu)

cmake_minimum_required(VERSION 2.8)

FIND_PACKAGE( OpenCV REQUIRED )

SET(SOURCES
  aplikacja1
  aplikacja2
  aplikacja3
  aplikacja4 
)

FOREACH(source ${SOURCES})
  ADD_EXECUTABLE(${source} ${source}.cpp)
  TARGET_LINK_LIBRARIES(${source} ${OpenCV_LIBS})
ENDFOREACH(source)

Jak łatwo zauważyć, dodawanie nowego programu do kompilacji nie wymaga wiele wysiłku. Wystarczy dodać nazwę pliku z kodem źródłowym w sekcji SOURCES i gotowe.

Życzę przyjemnej kompilacji programów OpenCV :-)

wtorek, 22 marca 2011

Dostęp do składowych piksela w OpenCV 2.2

2 komentarze
Pełny kod źródłowy
Wraz ze zmianą wersji biblioteki OpenCV z 2.1 na 2.2 doszło do wielu zmian nie tylko w zakresie organizacji modułów, ale również w zakresie sposobu programowania. Dokładnie nie śledziłem jakie zaszły zmiany, więc nie będę ich dokładnie opisywał, jednak zauważyłem, że został położony większy nacisk na programowanie obiektowe. Widoczne jest to szczególnie w strukturach przechowujących obraz. Od zawsze do tego celu korzystało się ze struktury IplImage, natomiast teraz zalecane jest używanie klasy cv::Mat, która reprezentuje wielowymiarowe macierze danych. Aby szczegółowo zapoznać się z konstrukcją tej klasy najlepiej zajrzeć do oficjalnej dokumentacji pod hasło Basic Structures → Mat.

Pierwszym problemem podczas przejścia ze struktury IplImage do używania klasy Mat będzie zapewne to, jak odczytać i zmodyfikować zawartość poszczególnych składowych piksela. Do tej pory było kilka sposobów, żeby sobie z tym poradzić (polecam wpis na oficjalnym Wiki pod hasłem: How to access image pixels). Teraz podobnie, mamy kilka możliwości, aby dostać się do piksela, jednak dokumentacja opisuje to bardzo pobieżnie. W rozdziale Introduction → Fast Element Access zostały pokazane 3 różne sposoby operowania na pikselach obrazu, jednak dla mnie wydają się one kłopotliwe w użyciu. To właśnie było powodem przygotowania niniejszego poradnika, w którym chciałem przedstawić własne i znalezione w Internecie wygodne sposoby dostępu do składowych piksela.

Obrazy w skali szarości

Na początek, aby nabrać wprawy najlepiej zrobić proste testy z wykorzystaniem obrazów 1-kanałowych. W tym celu obrazy pozyskane z kamery można przekonwertować na obraz szary i na nim wykonywać dalsze operacje.

Poniżej został pokazany fragment kodu, który zawiera 3 sposoby dostępu do piksela, począwszy od tego najbardziej tradycyjnego, gdzie operujemy bezpośrednio na tablicy z danymi (metoda 1), poprzez użycie funkcji at(), której przekazujemy współrzędne interesującego nas punktu (metoda 2), a skończywszy na zastosowaniu wskaźnika do każdego analizowanego wiersza obrazu (metoda 3). Z tych 3 metod podejście obiektowe jest reprezentowane przez sposób 2, podczas gdy pozostałe 2 przypadki działają bardziej tradycyjnie.

Aby skupić się na tym co istotne, poniższy kod zawiera jedynie najważniejszą część programu, z deklaracją używanych struktur reprezentujących obraz, oraz środkiem pętli przetwarzającej obraz z kamery. Aby uruchomić ten program można skorzystać z szablonu, który podałem w poprzednim wpisie OpenCV - instalacja i pierwszy przykład w Ubuntu w sekcji Ten sam przykład po nowemu.

Mat cam_frame, img_gray_v1, img_gray_v2, img_gray_v3;

// LOOP FOR GRABBING IMAGE FROM WEBCAM 

cap >> cam_frame;

// Method 1: Old style method operating on data array
cvtColor(cam_frame, img_gray_v1, CV_BGR2GRAY);

for(int i = 0; i < img_gray_v1.rows; i++)
  for(int j = 0; j < img_gray_v1.cols; j++) {
    img_gray_v1.data[img_gray_v1.step*i + j] = 255 - img_gray_v1.data[img_gray_v1.step*i + j];
  }

// Method 2: Assign pixel using .at() function
cvtColor(cam_frame, img_gray_v2, CV_BGR2GRAY);

for(int i = 0; i < img_gray_v2.rows; i++)
  for(int j = 0; j < img_gray_v2.cols; j++)
    img_gray_v2.at(i,j) = 255 - img_gray_v2.at(i,j);      

// Method2: Use plain C operator []. More efficient than method 2 
//    if you need to process a whole row of a 2d array
cvtColor(cam_frame, img_gray_v3, CV_BGR2GRAY);

for(int i = 0; i < img_gray_v3.rows; i++)
{
  uchar* img_gray_v3_i = img_gray_v3.ptr(i);
  for(int j = 0; j < img_gray_v3.cols; j++)
    img_gray_v3_i[j] = 255 - img_gray_v3_i[j];
}

// END LOOP

Obrazy wielokanałowe

Większy problem aniżeli obrazy 1-kanałowe sprawiają obrazy kolorowe, domyślnie uzyskiwane z tradycyjnych kamer cyfrowych. Należy tutaj pamiętać nie tylko o współrzędnych punktu, który jest analizowany, ale również o jego składowej koloru. na szczęście jest na to kilka sposobów, które można prześledzić poniżej.

Podejście tradycyjne

Podobnie jak w przypadku obrazów szarych, dla obrazów wielokanałowych można również skorzystać z podejścia znanego z obróbki struktur IplImage i przeliczać wskaźnik do elementu, który nas interesuje. Przykład poniżej:

Mat frame, result;

// LOOP FOR GRABBING IMAGE FROM WEBCAM 

cap >> frame;

result = frame.clone();

// invert the image
for(i=0; i < frame.rows; i++) 
  for(j=0; j < frame.cols; j++) 
    for(k=0; k < channels; k++) {

      uchar* temp_ptr = &((uchar*)(result.data + result.step*i))[j*3];
      temp_ptr[0] = 255 - temp_ptr[0];
      temp_ptr[1] = 255 - temp_ptr[1];
      temp_ptr[2] = 255 - temp_ptr[2];    
    }

// END LOOP

Sposoby opisane w oficjalnej dokumentacji

Tak jak wspomniałem na początku tego wpisu, w oficjalnej dokumentacji we wpisie Introduction → Fast Element Access pokazano 3 sposoby na to jak dostać się do składowych piksela. Dla mnie osobiście dziwne wydaje się rozbijanie obrazu wielokanałowego na obrazy zawierające jeden kanał i po wykonaniu obliczeń ponowne ich scalanie. Nie dość, że wydłuża to zapis algorytmu obróbki obrazu, to mam wrażenie, że powoduje dodatkowy narzut obliczeniowy. Kod z drobnymi poprawkami względem wersji oryginalnej znajduje się poniżej:

Mat img_frame, img_resultA, img_resultB, img_resultC;
vector planesA,planesB,planesC;

// LOOP FOR GRABBING IMAGE FROM WEBCAM 

cap >> img_frame;
    
// Method 1. process Y plane using an iterator

split(img_frame, planesA); // split the image into separate color planes

MatIterator_ 
  it1     = planesA[0].begin(),
  it1_end = planesA[0].end(),
  it2     = planesA[1].begin(),
  it3     = planesA[2].begin();

for(; it1 != it1_end; ++it1,++it2,++it3 )
{
  *it1 = 255 - *it1;
  *it2 = 255 - *it2;
  *it3 = 255 - *it3;
}

merge(planesA, img_resultA);

// Method 2. process the first chroma plane using pre-stored row pointer.

split(img_frame, planesB);

for( int y = 0; y < img_frame.rows; y++ )
{
  uchar* Uptr1 = planesB[0].ptr(y);
  uchar* Uptr2 = planesB[1].ptr(y);
  uchar* Uptr3 = planesB[2].ptr(y);
  
  for( int x = 0; x < img_frame.cols; x++ )
  {
    Uptr1[x] = 255 - Uptr1[x];
    Uptr2[x] = 255 - Uptr2[x];
    Uptr3[x] = 255 - Uptr3[x];
  }
}

merge(planesB, img_resultB);

// Method 3. process the second chroma plane using
//           individual element access operations

split(img_frame, planesC);

for( int y = 0; y < img_frame.rows; y++ )
{
  for( int x = 0; x < img_frame.cols; x++ )
  {
    uchar& Vxy1 = planesC[0].at(y, x);
    uchar& Vxy2 = planesC[1].at(y, x);
    uchar& Vxy3 = planesC[2].at(y, x);
    
    Vxy1 = 255 - Vxy1;
    Vxy2 = 255 - Vxy2;
    Vxy3 = 255 - Vxy3;        
  }
}

merge(planesC, img_resultC); 

// END LOOP

Ostatnia deska ratunku

Powyżej opisane sposoby dla obrazów wielokanałowych nie wydają się nazbyt wygodne i raczej zniechęcają, a nie zachęcają do stosowania klasy Mat. Na szczęście światełkiem w tunelu jest klasa pochodna po cv::Mat o niemal identycznej nazwie: cv::Mat_. Klasa ta ma opracowane operatory dostępu do składowych piksela poprzez zastosowanie konstrukcji ( x , y ). Możemy w ten sposób uzyskać wskaźnik do konkretnego punktu obrazu, i dalej stosując zapis tablicowy [] możemy dostać się do konkretnej wartości danego kanału.

Przykład 1: Operowanie na oryginalnym obrazie:

Mat frame;

// LOOP FOR GRABBING IMAGE FROM WEBCAM 

cap >> frame;

Mat_& frame_ = (Mat_&)frame;

for(int i = 0; i < frame_.rows; i++)
  for(int j = 0; j < frame_.cols; j++)
    for(int k = 0; k < 3; k++)
      frame_(i,j)[k] = 255 - frame_(i,j)[k];

// END LOOP

Przykład 2Operowanie na obrazie pomocniczym:

Mat frame;
Mat_ rgb;

// LOOP FOR GRABBING IMAGE FROM WEBCAM 

cap >> frame;

cvtColor(frame, rgb, CV_BGR2RGB);

for(int i = 0; i < rgb.rows; i++)
  for(int j = 0; j < rgb.cols; j++)
    for(int k = 0; k < 3; k++)
      rgb(i,j)[k] = 255 - rgb(i,j)[k];

// END LOOP

Podsumowując zebrane w tym poradniku sposoby dostępu do składowych piksela, najwygodniejsze wydaje się użycie operatora at() dla obrazów jednokanałowych,  natomiast dla obrazów wielokanałowych najprostszy i najbardziej czytelny zapis daje klasa cv::Mat_.

sobota, 19 marca 2011

OpenCV - instalacja i pierwszy przykład w Ubuntu

6 komentarze
Już od dłuższego czasu przymierzałem się, aby więcej czasu poświęcić systemom interaktywnym, a w szczególności problematyce analizy ruchu. Zagadnieniami wizualizacji i przetwarzania obrazów medycznych oczywiście nie przestaje się dalej zajmować, jednakże opisywanie tej tematyki na blogu nie dość, że było i jest bardzo wymagające czasowo, to niestety interesuje tylko bardzo małą grupę osób. Natomiast analiza ruchu ma wiele różnych zastosowań - nie tylko tych naukowych, ale również rozrywkowych. Podobnie z punktu widzenia nauki przetwarzania informacji obrazowej, dla wielu młodych osób ciekawsze wydaje się analizowanie obrazu z kamerki na żywo, zamiast analizy statycznych obrazów medycznych.

Tym wpisem rozpoczynam serię poradników dotyczących właśnie analizy ruchu. Głównym narzędziem (biblioteką) jak będzie używana będzie OpenCV, o którym pisałem ponad 2 lata temu na tym blogu. Dzisiaj chciałbym opisać proces instalacji tej biblioteki w Ubuntu i pokazać prosty przykład z użyciem kamerki internetowej.

Instalacja z repozytorium

Aby zainstalować OpenCV z repozytorium wpisujemy następujące polecenie w okienku terminala:
sudo apt-get install libcv-dev libcvaux-dev libhighgui-dev

Patrząc na tą komendę można zauważyć, że instalowane są tylko pakiety programistyczne. A co z bibliotekami? Zainstalują się one oczywiście same jako zależności wyżej wymienionych pakietów. Takie podejście jest oczywiście bardziej uniwersalne w przypadku instalacji OpenCV, ponieważ biblioteki te mają dodaną końcówkę 2.1 (np. libcv2.1), a tak nie będzie zawsze. Dla przykładu na stronie projektu jest już dostępna wersja 2.2.

Instalacja ze źródeł

Tak jak wspomniałem powyżej, wersja, która znajduje się w repozytorium nie jest najświeższa i osobom, którym szczególnie zależy, aby pracować na ostatniej wersji tej biblioteki polecam samodzielną kompilację ze źródeł. Nie jest ona skomplikowana, dlatego również zostanie opisana w tym poradniku.

Najnowszą stabilną wersję źródeł OpenCV można pobrać z portalu SourceForge, a dokładnie ze strony: http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/. Można pobrać ją również bezpośrednio z repozytorium, aby mieć dostęp do aktualnie wprowadzanych funkcji. W tym celu wystarczy wpisać w konsoli następujące polecenie:
svn co https://code.ros.org/svn/opencv/trunk

Ja osobiście polecam wersję stabilną. Obecnie jest to wersja 2.2.

Teraz kiedy mamy pobrane już źródła biblioteki OpenCV, możemy przystąpić do jej kompilacji. Wykonujemy w tym celu następujące kroki:
  • Utworzenie katalogu build i uruchomienie w nim graficznej nakładki na CMake:
    mkdir build
    cd build
    cmake-gui ../
  • Przy pierwszej kompilacji najlepiej nie ustawiać zbyt wiele opcji, aby mieć pewność że podstawowa wersja się skompiluje. Ja ustawiłem tylko typ kompilacji na „Release
    CMAKE_BUILD_TYPE                 Release
  • Uruchomienie kompilacji. Jeśli mamy wiecej niż jeden rdzeń warto z tego skorzystać stosując przełącznik j:
    make -j2
  • Jeśli wszystko dobrze się skompiluje można wówczas uruchomić kolejne przebiegi kompilacji z włączonymi następującymi opcjami:
    BUILD_EXAMPLES                   ON
    BUILD_NEW_PYTHON_SUPPORT         ON
    OPENCV_BUILD_3RDPARTY_LIBS       ON
    Oczywiście tych opcji jest dużo więcej, dlatego polecam samodzielne testowanie pozostałych, chociaż te o których napisałem powinny w zupełności wystarczyć.
Jeśli pojawiły się jakieś niespodziewane błędy podczas kompilacji polecam zajrzeć na stronę:
http://opencv.willowgarage.com/wiki/InstallGuide w celu znalezienia rozwiązania.

Pierwsze testy

Na początek warto przetestować przykłady załączone w katalogu samples. Po kompilacji odpowiadające im wersje binarne powinny znaleźć się w katalogu: build/bin/. Ja sprawdziłem wszystkie i od razu mogę podpowiedzieć, że z kamerką działają te z nich:
  • adaptiveskindetector
  • bgfg_codebook
  • bgfg_segm
  • camshiftdemo
  • fback
  • fback_c
  • laplace
  • lkdemo
  • motempl
  • segment_objects
Pomimo tego, że nie są one szczególnie złożone, na początek warto zacząć od jeszcze prostszych przykładów.

Wyświetlanie obrazu z kamery

Jednym z pierwszych przykładów, które warto przeanalizować i uruchomić w OpenCV jest pobieranie obrazu z kamery i wyświetlenie go na ekranie monitora. Nie jest to oczywiście trudne, ale wymaga znajomości kilku elementarnych funkcji takich jak:
  • cvCaptureFromCAM - inicjalizacja kamery,
  • cvQueryFrame - pobranie pojedynczej klatki obrazu,
  • cvShowImage - wyświetlenie obrazka we wskazanym oknie.
Cały przykład wygląda następująco:
#include "opencv/highgui.h"

int main() 
{
  CvCapture *cam = cvCaptureFromCAM(-1);
  
  const char *window = "Example 1";
  cvNamedWindow(window, CV_WINDOW_AUTOSIZE);
  
  while (cvWaitKey(4) == -1) {
    IplImage *frame = cvQueryFrame(cam);
    cvShowImage(window, frame);
  }
  
  cvDestroyAllWindows();
  cvReleaseCapture(&cam);
  
  return 0;
}

Aby go skompilować wystarczy uruchomić:
gcc camera1.cpp -o camera1 -lhighgui

Ten sam przykład po nowemu

Przykład przedstawiony powyżej działa zarówno w bieżącej wersji OpenCV jak i w wersjach poprzednich. Jednakże własnie od wersji bieżącej 2.2 biblioteka ta została uporządkowana i podzielona na moduły. Dodatkowo zostały wprowadzone nowe funkcje i został zaproponowany bardziej obiektowy model programowania. Wszystkie te zmiany mają za zadanie ułatwić programowanie, ale nie pozwalają już na kompilację nowych programów tam gdzie jest stara wersja biblioteki. Program po zmianach wg nowych zaleceń wygląda tak:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main(int, char**)
{
  VideoCapture cap(0);
  if( !cap.isOpened() ) return -1;
  
  Mat frame;
  
  const char *window = "Example 2";
  namedWindow(window, CV_WINDOW_AUTOSIZE);
  
  while (cvWaitKey(4) == -1) {
    cap >> frame;
    imshow(window, frame);
  }
  
  return 0;
}

Kompilacja tak napisanego programu w konsoli nie jest już taka trywialna jak poprzednio. W takiej sytuacji najlepiej będzie skorzystać z narzędzia CMake, które jest podstawą budowania całej biblioteki OpenCV. W katalogu ze źródłami omawianych aplikacji tworzymy nowy plik CMakeLists.txt. Powinien on zawierać taką treść:

PROJECT(opencv_example)

cmake_minimum_required(VERSION 2.8)

FIND_PACKAGE( OpenCV REQUIRED )

# Declare the target (an executable)
ADD_EXECUTABLE(camera1 camera1.cpp)
TARGET_LINK_LIBRARIES(camera1 ${OpenCV_LIBS})

ADD_EXECUTABLE(camera2 camera2.cpp)
TARGET_LINK_LIBRARIES(camera2 ${OpenCV_LIBS})

Teraz już kompilacja sprowadza się do wpisania w konsoli:

mkdir build
cd build
cmake-gui ../

i określenia w parametrach CMake ścieżki do katalogu gdzie mamy zbudowany OpenCV. U mnie wygląda to tak:

OpenCV_DIR   /home/rafal/installed/opencv/OpenCV-2.2.0/build

Teraz już wystarczy wpisać make i oba programy zostaną skompilowane.

W ten sposób udało nam się przygotować dwie aplikacje, które niby nie robią wiele, ale stanowią szkielet większości aplikacji interaktywnych w OpenCV.

czwartek, 3 marca 2011

Nie do końca udana wirtualizacja MeeGo w VirtualBoxie

2 komentarze
Na początek od razu wyjasnię o co chodzi w tytule, bo wiem, że może on nie zachęcać do czytania dalej. Przez ostatnie kilka dni, mając trochę wolnego czasu postanowiłem przetestować pełną wersję MeeGo Netbook w środowisku wirtualnym z którego zawsze korzystam, czyli w VirtualBoxie. Skłoniło mnie do tego nie tylko to, że wersja dostępna w emulatorze QEMU (jak zainstalować środowisko uruchomieniowe pisałem we wpisie MeeGo - pierwsze starcie) jest mocno okrojona, ale również to, że działa ona dosyć powoli. Miałem nadzieję, że w VirtualBoxie będzie inaczej, bo to w końcu uznana marka wśród narzędzi do wirtualizacji. Sama instalacja pomimo tego, że nie obyła się bez problemów zakończyła się sukcesem. Niestety problem z powolnym działaniem systemu i brakiem jego responsywności również tutaj był mocno widoczny. Próbowałem różnych sposobów i ostatecznie żaden nie pomógł. Nawet deweloperzy MeeGo sami twierdzą, że z VirtualBoxem mogą być problemy i w miarę możliwości zachęcają do instalacji systemu na kompatybilnych urządzeniach.

Pomimo tego, że MeeGo w VirtualBoxie nie działa zachwycająco, to dla osób, które nie mają odpowiedniego sprzętu do dyspozycji lub nie chcą instalować kolejnego systemu jedynie w celach testowych na maszynie, na której pracują na co dzień, myślę, że zastosowanie VirtualBoxa może być dobrym rozwiązaniem. W tym wpisie nie będę szczegółowo rozpisywał się na jakie problemy napotkałem podczas instalacji MeeGo w VirtualBoxie, a jedynie przedstawię niezbędne kroki, które pozwolą na instalację i uruchomienie systemu.

Pobranie obrazu instalacyjnego

Płytę z obrazem instalacyjnym MeeGo Netbook pobieramy ze strony: http://meego.com/downloads/releases/netbook. Ponieważ VirtualBox nie widzi płyt img możemy bez żadnego problemu zmienić rozszerzenie pobranego pliku na iso.

Utworzenie nowej maszyny wirtualnej

Dalej należy utworzyć pustą maszynę wirtualną. W kreatorze VirtualBoxa, który do tego służy możemy podać następujące parametry:
  • nazwa: MeeGo Netbook v1.1
  • typ systemu: Linux/Fedora
  • pamięć: 512MB
  • dysk: dynamicznie rozszerzalny, 8GB
Dodatkowo samodzielnie należy wejść do opcji i ustawić parametry jak poniżej:
  • SystemProcesorWłącz PAE/NX
  • EkranWideoWłącz akcelerację 3D
  • Nośnikikontroler IDEChoose a virtual CD disc file (wskazujemy na wcześniej pobrany plik z obrazem).
Instalacja MeeGo NetBook

Po uruchomieniu systemu wirtualnego powinno nam się pojawić okienko jak poniżej:

Wybieramy na nim opcję "Instalation only". Po chwili czekania powinna się rozpocząć instalacja systemu. Wita nas ona takim obrazkiem:

Na kolejnych ekranach wystarczy jedynie ustawić język i skonfigurować dysk. W przypadku pustego dysku wirtualnego nie jest to zbytnio skomplikowane. Potwierdzamy jedynie komunikaty, które się pojawią. O zakończeniu instalacji zostaniemy powiadomieni obrazem jak poniżej:
Kliknięcie na przycisk Zamknij spowoduje restart maszyny wirtualnej. Warto ją w tym momencie w ogóle zatrzymać i odmontować z napędu CD płytę instalacyjną.

Po ponownym uruchomieniu systemu powinniśmy zobaczyć kreator pierwszego uruchomienia. Pyta nas on o ustawienia klawiatury, strefę czasową i prosi o utworzenie użytkownika.

Jeśli system teraz wystartuje to mamy szczęście :-) Ja tego szczęścia niestety nie miałem i zobaczyłem czarny ekran. Po ponownym restarcie komputera wyświetlił mi się tylko obraz tła.

Problem przy pierwszym uruchomieniu

Przy rozwiązywaniu problemów, które zaczęły się pojawiać bardzo pomocna okazała się ta strona na Wiki MeeGohttp://wiki.meego.com/MeeGo_1.0_Netbook_VirtualBox. Korzystając z porad tam zawartych wykonałem następujące czynności:
  • Resetujemy maszynę wirtualną i zanim zacznie startować system wciskamy Escape, a następnie Tab.
  • Pojawi nam się linijka z tekstem jak na obrazku poniżej, którą możemy wyedytować. Kasujemy tutaj słowo 'quiet' i dodajemy literkę 's'.
  • Klikamy Enter i czekamy. Po chwili powinniśmy zobaczyć wiersz poleceń ze znaczkiem zachęty symbolizującym tryb administracyjny. Skoro już tutaj jesteśmy warto ustawić hasło roota (polecenie 'passwd') i zainstalować 2 przydatne narzędzia (wget i nano), które mogą okazać się niezbędne na kolejnych etapach konfiguracji.
    zypper install wget nano
  • Następnie w konsoli wpisujemy następujące polecenie:
    chmod +s /usr/bin/Xorg
  • i restartujemy system:
    reboot
Teraz system powinien wystartować, ale wcale nie ma takiej pewności :-) U mnie na jednym komputerze opisane podejście zadziałało, a na innym nie przyniosło żadnego rezultatu.

Jeśli system ciągle nie startuje warto sprawdzić, czy nie występuje problem jak ten opisany na forum MeeGo w wątku: INIT: Id "x" respawning too fast: disabled. U mnie właśnie tak było i polecam sprawdzić opisane tam rozwiązanie.

Jeśli będziemy mieć szczęście (a na pewno w końcu się uda ;) ) to system powinien  wystartować i przywitać nas ekranem jak ten poniżej:

Próba włączenia wsparcia OpenGL

Niestety, tak jak wspomniałem na początku, MeeGo w podstawowej konfiguracji w Virtualboxie nie zachwyca szybkością - chodzi tak samo ociężale jak wersja dostępna na QEMU. Na Wiki MeeGo jest rozwiązanie tego problemu, ale przyznam szczerze, że u mnie nie działa. Testowałem to na kilka sposobów i albo nie było żadnego efektu, albo system nie mógł wystartować. Opiszę jednak kroki, które wykonałem, bo może u kogoś zadziała lub po prostu ktoś będzie w stanie podpowiedzieć mi co źle robiłem.

Po kolei co należy zrobić, aby spróbować uruchomić akcelerację OpenGl w MeeGo zainstalowanego w VirtualBox (w skrócie):
  • Uruchamiamy okienko terminala: zakładka Aplikacje → Narzędzia systemowe.
  • Instalujemy następujące pakiety i restartujemy system:
    sudo zypper install gcc make kernel-netbook-devel patch nano wget yum yum-utils 
    sudo reboot
  • Instalujemy dodatki VirtualBoxa. Przed wykonaniem poniższych czynności najpierw należy wybrać w opcjach maszyny: Urządzenia → Zainstaluj dodatki.
    sudo mount /dev/sr0 /mnt 
    cd /mnt 
    sudo ./VBoxLinuxAdditions-x86.run
    sudo reboot
  • Tworzymy katalog tymczasowy i próbujemy pobrać źródła Cluttera z repozytorium:
    cd ~
    mkdir tmp
    cd tmp
    yumdownloader --source clutter
  • Niestety u mnie ta próba kończy się niepowodzeniem. Dostaję komunikat podobny do tego:
    Error: Cannot retrieve repository metadata (repomd.xml) for repository: meego-core. Please verify its path and try again 
  • Nie pozostaje nam zatem nic innego jak samodzielne pobranie odpowiedniego archiwum ze źródłami
    wget http://repo.meego.com/MeeGo/releases/1.1/core/repos/source/clutter-1.2.8-2.131.src.rpm
    rpm2cpio clutter-1.2.6-2.2.src.rpm|cpio -id
    tar jvxf clutter-1.2.6.tar.bz2
  • Następnie pobieramy zależności do zbudowania Cluttera. Można to zrobić instalując pakiet clutter-devel, co pozwoli na automatyczne dociągnięcie wszystkich zależnych pakietów:
    sudo zypper install clutter-devel
  • Ostatecznie uruchamiamy procedure budowania i instalacji Cluttera. Między czasie pobieramy i stosujemy dodatkowa łatkę z forum MeeGo.
    cd clutter-1.2.8
    wget http://wiki.meego.com/images/Clutter-xvisual-patch.txt
    patch -p1 < ./Clutter-xvisual-patch.txt
    ./configure --prefix=/usr
    make
    sudo make install
    reboot
Po wykonaniu opisanych czynności restartujemy komputer. Należ się również upewnić, że jest włączona akceleracja 3D w ustawieniach VirtualBoxa.

Prezentacja systemu

Na koniec wpisu załączam małą galerię slajdów wykonanych nie tylko na kolejnych etapach instalacji i konfiguracji MeeGo w Virtualboxie, ale również slajdy prezentujące wygląd poszczególnych ekranów systemu.