Lý thuyết về Camera calibration ứng dụng Robot

Đăng lúc: Thứ năm - 27/10/2016 09:59 - Người đăng bài viết: SuperG
Lý thuyết về Camera calibration ứng dụng Robot

Lý thuyết về Camera calibration ứng dụng Robot

Camera calibration tạm hiểu là một phương pháp tính toán và thực nghiệm nhằm tìm ra các thông số của camera cho việc tái tạo không gian 3D của một cảnh nào đó trong thực tế bằng những ảnh mà camera đó chụp lại được.

Để có được những thông số đó, các tính toán sau chủ yếu dựa vào mô hình camera thông dụng nhất hiện nay: mô hình Pinhold. 


Về mặt hình học, mô hình này bao gồm một mặt phẳng ảnh I (Image plane) và một tâm điểm C (Eyepoint) nằm trên mặt phẳng tiêu cự F (Focal plane), mô hình như sau:
 
 
Một đặc điểm rất cơ bản của mô hình này là tất cả những điểm ảnh m trên mặt phẳng ảnh I được tạo thành bởi điểm vật M qua C sẽ là thẳng hàng với C và M, có nghĩa m, C, M là nằm trên một đường thẳng. Điểm C còn được gọi là tâm quang (Optical center), đường thằn cC vuông góc với I và F được gọi là trục quang (Optical axis), c được gọi là điểm chính (Principal point).
Gọi (C,X,Y, Z) là hệ tọa độ camera, (c,x,y) là hệ tọa độ của các điểm ảnh. Ta có thể thấy rằng rõ rang                                              x/X = y/Y = f/Z                                  (1).
Từ góc độ hình học mà nói, sẽ không có sự khác biệt gì khi thay mặt phẳng I bằng một mặt phẳng ào nằm ở phía bên kia mặt phẳng F. Trong hệ tọa độ mới này, mỗi điểm (x,y) giờ đây sẽ có tọa độ 3D là (x,y,f). 
 
 
Trong phép chiếu hình học ta đã biết rằng tất cả những điểm nằm trên một đường thẳng vuông góc với mặt phẳng chiếu thì khi chiếu xuống mặt phẳng đó ta chỉ thu được một điểm duy nhất,  do đó với bất kí một điểm (X,Y,Z) nào đó thì tỉ lệ sau s(X,Y,Z) hay (sX, sY, sZ) (với s bất kì) khi chiếu qua điểm C ta cũng chỉ thu được một điểm m(x,y) duy nhất. Từ lập luận trên và (1) ta có: 
 


  


Phương trình (1) có thể được viết lại như sau:
 
Trong đó, x = [x, y]T và đặt x’ = [x,y,1] là vector x thêm 1 vào phần tử cuối cùng.  Ma trận:
 

gọi là ma trận chiếu phối cảnh. 
 
Như vậy với mỗi một điểm M(X,Y,Z) và một điểm ảnh tương ứng m(x,y) ta có thể viết lại
sm’ = PM’   (3)    trong đó m’(x,y,1) và M’(X,Y,Z,1).
Trong thực tế thì một đối tượng thật có thể biểu diễn bởi một hệ tọa độ 3D bất kì mà không phải là tọa độ camera như ta giả sử. Để tính toán được trên các hệ tọa độ này, cách đơn giản nhất là ta chuyển nó về hệ tọa độ camera. Giả sử rằng Mw la một điểm bất kì trong hệ tọa độ w bất kì, Mc là một điểm trong hệ tọa độ camera. Khi đó, Mw có thể chuyển về Mc bằng một phép quay R và một phép tịnh tiến t.
Mc = RMw + t.
Hay tổng quát hơn, M’c = DM’w    (4)  trong đó: 
 
 
 
 
 
 
 
 
 


Ma trận R và vector t mô tả hướng, vị trí tương đối giữa hệ tọa độ camera và hệ tọa độ thực tế (word cs). Ma trận R chứa 3 phép quay (theo x,y,z) và vector v chứa 3 phép tịnh tiến. Những thông số chứa trong R và t được gọi là những thông số ngoai của camera (extrinsic).
 

Từ (3) và (4) ta có:                    m’ = PM’ = PDM’w.               (5)
Trong thực tế, tâm của ảnh không phải lúc nào cũng là điểm chính c. và tỉ lệ theo các trục x, y không phải lúc nào cũng như nhau. Người ta sử dụng một ma trận K để diễn tả những sai lệch đó và cuối cùng mối quan hệ giữa một điểm trong thực tế Mw và một điểm ảnh m có thể được diễn tả từ công thức sau:
                                                m’ = KPDM’w                         (6)
hay cụ thể hơn :
 
Ma trận K được gọi là ma trận thông số nội của camera, nó gồm 5 thông số sau:
 
Trong đó, ku, kv là tỉ lệ dọc theo hai trục của ảnh. u0, v0 là điểm chính của hệ tọa độ ảnh(gốc tọa độ, thay cho c ở trên). Góc theta thể hiện đô méo giữa hai trục u, v. nếu trong ảnh lý tưởng (u,v) vuông góc với nhau thì góc này bằng 0.

 Có được mối quan hệ giữa các điểm ảnh và điểm ở ngoài thực tế đồng nghĩa với việc ta có thể tái tọa lại những điểm thực tế 3D dựa trên các ảnh thu được, tuy nhiên việc đầu tiên và quan trọng là ta phải tìm ra được các thông số của camera. Có 5 thông số nội và 12 thông số ngoại (9 thành phần của vector quay R và 3 thành phần của vector tịnh tiến t) cần phải tìm. Việc đi tìm các thông số này được gọi là quá trình calibrate camera. Vì mỗi camera có ống kính, khác nhau, vị trí khác nhau … nên không có một thông số chung cho tất cả các loại camera, ta phải lam cho từng camera một. ​

Để thực hành tìm ra cho việc tìm ra các thông số của camera các bạn có thể Tìm hiểu thêm bài sau:

Giới thiệu cách cài đặt camera calibration sử dụng thư viện OpenCV C++ để thu được bảng các thông số nội của camera (camera intrinsic). 

Công việc cần chuẩn bị trước.
Chuẩn bị một bàn cờ (loại bàn cờ vua). Kích thức của bàn cờ là tùy ý, tuy nhiên không nên quá nhỏ so với tầm nhìn của camera, thông thường nên in bàn cờ trên một khổ giấy A0 là vừa. Số lượng các ô trên bàn cờ có thể là 8x8, 7x10 ... Miễn là diện tích các ô vuông phải bằng nhau. Nếu in bàn cờ trên giấy, nên để chúng trên một mặt phẳng (tấm kính, gỗ ...) để chúng luôn được phẳng, không bị biến dạng.

Sau khi đã có bàn cờ, ta dùng camera đặt ở một vị trí cố định, duy chuyển bàn cờ quanh camera với những góc nhìn khác nhau, ở từng vị trí đó ta chụp lại ảnh chứa bàn cờ. Số lượng ảnh có thể là vài chục cái.( Thông thường tôi hay chụp 50 kiểu ảnh ở 50 góc nhìn khác nhau). Ta lưu số ảnh này vào một folder làm cơ sở dữ liệu cho các tính toán sau này.

Lập trình camera calibration
Chương trình sử dụng thư viện OpenCV C++, tôi sử dụng trình dịch Eclipse có sự giúp đỡ của QT. Toàn bộ code rất đơn giản và có chú thích rõ ràng, chỉ riêng mục đọc các file ảnh trong một folder tôi sử dụng lớp QDirIterator của QT. Nếu các bạn không dùng QT có thể dùng bất kì thư viện nào miễn là đọc được các file trong folder (Như các thư viện của MFC hoặc thư viện riêng về file và folder dirent.h ...).
Trước hết hãy tạo một project mới hoạt động với OpenCV:

Trước hết các bạn download thư viện OpenCV về. Hiện có nhiều phiên OpenCV khác nhau, các bạn nên download bản mới nhất về dùng, Ở đây tôi giả sử đang dùng bản 2.3.1. Tiếp theo các bạn cài đặt thư viện lên, việc cài đặt ở đây thực chất là giải nén thư viện OpenCV vào một thư mục nào đó, các bạn cài đặt như bình thường, ở đây tôi giả sử là cài vào thư mục C:\. Sau khi cài đặt ta sẽ có thư mục C:\opencv và bên trong có rất nhiều thư mục con.
Sử dụng OpenCV với Eclipse CDT và trình dich MinGW GCC.
Từ cửa sổ Eclipse chọn New -> C++ Project , hộp thoại C++ Project xuất hiện, trong hộp thoại ta chọn Project name là opencv, Project type là Hello World C++ Project, Toolchains là MinGW GCC.
 



Chọn Finish và ta có một Project mới. OK, bây giờ configure cho project này hoạt động được với OpenCV
Trong cửa sổ của Eclipse chọn Project ->Properties, cửa sổ Properties hiện ra. Tron cửa sổ Properties chọn C/C++ Build->Settings. Trong tab Tool Settings. Ở phần GCC C++ Compiller chọn Include rồi dẫn đường dẫn tới mục Include của OpenCV là C:\opencv\build\include. Trong phần MinGW C++ Linker chọn Library và chọn các mục như sau: click vào dấu cộng ở Library search path (-L) và dẫn tới thư mục lib: C:\opencv\build\x86\mingw\lib đối với Windows 32 bit hoặc C:\opencv\build\x64\mingw\lib đối với Windows 64 bit. Tiếp đó click vào dấu "cộng" để thêm Library(-I) vào, các library cần thêm lần lượt là: opencv_core231, opencv_highgui231, opencv_imgproc231 ... nói chung là tùy vào nhu cầu sử dụng có thể thêm một hoặc nhiều lib vào.




Nhấn OK để hoàn thành, như vậy là configure xong, bây giờ là viết một chương trình đơn giản là load và hiển thị một ảnh từ máy tính.
Trong file opencv.cpp thêm vào header : #include  . Việc thêm header này vào sẽ tự động thêm tất cả các thư viện của opencv vào trong project. Tuy nhiên các bạn cũng có thể thêm thủ công vào project của mình bằng cách thêm các thư viện #include #include  ...
Toàn bộ chương trình đơn giản như sau : 

#include 
#include 
using namespace std;

int main() {
    cout << "The first program in opencv" << endl;
    IplImage *img = cvLoadImage("D:\\Test\\test.jpg", CV_LOAD_IMAGE_COLOR);
    cvNamedWindow("Test", CV_WINDOW_NORMAL);
    cvShowImage("Test", img);
    cvReleaseImage(&img);
    return 0;
}



Chương trình đã hoàn tất, tuy nhiên lúc này để chạy được ta cần copy các file DLL trong thư mục C:\opencv\build\x86\mingw\bin vào thư mục chứa file chạy (opencv.exe) hoặc vào trong thư mục C:\WINDOWS\system32. 
Giờ thị build và chạy chương trình, ta sẽ thấy một cửa sổ ảnh Test hiện ra. Ok, xong phần với eclipse. 


Sử dụng OpenCV với Visual Studio

Phiên bản Visual studio sử dụng ở đây là phiên bản Visual studio 2010, các version trước các bạn có thể cấu hình một cách tương tự.
Tạo một project mới: New > Project, trong cửa sổ New Project chọn Visual C++, Win32 console application. Đặt tên project là opencv




Nhấn OK, Next, Finish và ta có một project mới. Bây giờ vào Project > Properties hoặc nhấn Alt + F7 để mở hộp thoại property. Hộp thoại opencv property page hiện ra, Trong mục Visual C++ Directories, chọn Include Directories, dẫn tới đường dẫn chứa thư mục include của opencv, ở đây là C:\opencv\build\include



Tương tự như vậy, trong mục Lybrary Directories chọn đường dẫn tới C:\opencv\build\x86\vc9\lib
Trong mục Liker > Input > Additional Dependence ta thêm vào các lib: opencv_core231.lib,
opencv_imgproc231.lib, opencv_highgui231.lib
 ... Tùy vào mục đích chương trình mà ta có thể thêm nhiều hoặc tất cả các lib vào.



Để máy tính có thể chạy được chương trình ta cần phải chỉnh phần PATHenvironment variable, tuy nhiên để đơn giản tôi thường copy hêt các file *.dll trong thư mục C:\opencv\build\x86\vc9\bin vào thư mục C:\Windows\System32 hoặc vào thư mục chứa file chạy (opencv.exe) trong project để có thể chạy được trên máy khác khi copy thư mục bin của project từ máy mình sang máy khác.
Cài đặt xong, bây giở viết chương trình đơn giản load ảnh và hiển thị ảnh:

#include "stdafx.h"
#include <opencv2/opencv.hpp>

int _tmain(int argc, _TCHAR* argv[])
{
    IplImage *src = cvLoadImage("D:\\Temp_work\\opencvgiude2.jpg", CV_LOAD_IMAGE_COLOR);
    cvNamedWindow("a", 1);
    cvShowImage("a", src);
    cvWaitKey(10);
    return 0;
}


OK, giờ thì build và chạy chương trình, ... 

Sau đó hãy pass đoạn code sau :



#include ... //include tất cả các header cần thiết. void cva_calib(QString img_path){ int numCornersHor = 14; int numCornersVer = 10; int numSquares = numCornersHor*numCornersVer; int error = 0; cv::Size board_sz = cv::Size(numCornersHor, numCornersVer); std::vector object_points; std::vector image_points; std::vector corners; std::vector obj; for(int j=0;j(0, 4) = 0; std::vector rvecs; std::vector tvecs; cv::calibrateCamera(object_points, image_points, gray.size(), intrinsic, distCoeffs, rvecs, tvecs, CV_CALIB_FIX_K3); std::cout<<"------------------------------------------"<

kết quả cuối cùng được lưu trong ma trận 3x3 intrinsic. Các bạn có thể sử dụng kết quả này cho mục đích sau này của mình!

 

 

Hoặc nâng cao hơn nữa thì đọc bài viết của mình bằng tiếng anh tại đây.

 

Đánh giá bài viết
Tổng số điểm của bài viết là: 5 trong 1 đánh giá
Click để đánh giá bài viết
 

Quy trình xử lý

Hướng dẫn quý khách hàng tìm hiểu làm quen với cách sử dụng sản phẩm và dịch vụ trong lĩnh vực Robot gia dụng chúng tôi cung cấp. Đặt vấn đề: Khách hàng liên hệ qua Email hoặc Điện thoại, ghi chú nội dung liên hệ và thông tin yêu cầu sản phẩm dịch vụ sơ bộ. Xử lý thông tin: Chúng tôi sẽ trực...

Thăm dò ý kiến

Bạn có muốn sở hữu một Robot trong nhà không?

Cần một Robot để dọn dẹp

Cần một Robot trông nhà

Cần một Robot để giải trí

Bạn cần một Robot theo cách khác

Bạn đã có rồi

Bạn không cần

Liên kết