Copyright © Michal Sitko
Posty i artykuły na tym blogu są objęte prawem autorskim. Ich kopiowanie / używanie bez pisemnej zgody autora jest zabronione.
(Ustawa z dnia 4 lutego 1994 r. o prawie autorskim i prawach pokrewnych, Dz.U. z 1994 r. Nr 24, poz. 83)

Posts and articles on this blog are copyrighted. Their copying / use without written permission of the author is prohibited. Copyright is protected by Polish and international law.

czwartek, 12 stycznia 2012

Computer Vision: wyznaczanie środka masy obiektu

Środek masy (ang. center of mass) obiektu to punkt, w którym skupiona jest cała masa w opisie układu jako masy punktowej. Pojęcie te dotyczy także geometrii, a zatem również wizji komputerowej.

Z punktu widzenia wizji komputerowej, środek masy obiektu może być wykorzystywany do opisu cech klasyfikowanego obiektu. Samo jego położenie nie jest może szczególnie istotne, ale jego położenie względem innych kluczowych (charakterystycznych) punktów obiektu może już być decydujące w procesie klasyfikacji. 
Prostym przykładem może być wykrywanie gestów dłoni - jeśli na obrazie zostaną wykryte punkty końców palców, a także środek masy dłoni, to wzajemne położenie końcówek palców względem środka masy może już w jakiś sposób opisywać ułożenie dłoni.

Rozważmy poniższy obrazek:


Obiekt O na obrazie I


Mamy tutaj obiekt O, umiejscowiony na obrazie I. Możemy sobie wyobrazić, że obiekt ten został wyznaczony po procesie segmentacji.
Jeśli obraz I zawiera obiekt O, przy czym obraz opisany jest za pomocą współrzędnych kartezjańskich (x,y), gdzie (x,y) należy do I, to możemy zdefiniować funkcję b charakteryzującą obiekt O:



Pole powierzchni Po obiektu O określa równanie:



Środek masy obiektu natomiast dany jest wzorem:


gdzie:



Ponieważ obraz komputerowy jest obrazem dyskretnym o skończonej rozdzielczości, operacja całkowania upraszcza się do operacji sumowania.

Implementacja obliczeń w języku C# z wykorzystaniem biblioteki EmguCV może wyglądać tak:

Code Snippet
  1.  
  2. int b(int x, int y, Image<Gray, byte> img)
  3. {
  4.     return img.Data[y, x, 0] == 0 ? 0 : 1;
  5. }
  6. int Area(Image<Gray, byte> img)
  7. {
  8.     int d = 0;
  9.  
  10.     for (int y = 0; y < img.Height; y++)
  11.         for (int x = 0; x < img.Width; x++)
  12.             d += b(x, y, img);
  13.     return d;
  14. }
  15.  
  16. void CalculateMassCentre(Image<Gray, byte> img, out int x0, out int y0)
  17. {
  18.     int area = Area(img);
  19.     x0 = y0 = 0;
  20.     
  21.     for (int y = 0; y < img.Height; y++)
  22.         for (int x = 0; x < img.Width; x++)
  23.         {
  24.             x0 += x * b(x, y, img);
  25.             y0 += y * b(x, y, img);
  26.         }
  27.     x0 = x0 / area;
  28.     y0 = y0 / area;
  29. }

i samo wywołanie:

Code Snippet
  1.  
  2. Bitmap bmp = new Bitmap(fileIn);
  3. Image<Bgra, byte> image = new Image<Bgra, byte>(bmp);
  4. Image<Gray, byte> gray = new Image<Gray, byte>(bmp.Size);
  5. gray.ConvertFrom<Bgra, byte>(image);
  6.  
  7. int x0, y0;
  8. CalculateMassCentre(gray, out x0, out y0);
  9.  
  10. image.Draw(new CircleF(new PointF(x0, y0), 5), new Bgra(0, 0, 255, 255), 4);
  11.  
  12. CvInvoke.cvShowImage(fileIn, image.Ptr);
  13. CvInvoke.cvWaitKey(0);
  14. CvInvoke.cvDestroyWindow(fileIn);


Poniżej wyniki:

 Prostokąt

 Prostokąt z wyznaczonym środkiem masy


 Otwarta dłoń

 Otwarta dłoń z wyznaczonym środkiem masy


 Dłoń w geście OK

Dłoń w geście ok z wyznaczonym środkiem masy


0 komentarze:

Prześlij komentarz