Thƣ viện ngƣời dùng đồ họa mức cao

Một phần của tài liệu Thuật toán phát hiện chuyển động (Trang 55)

Các hàm OpenCV cho phép chúng ta có thể giao tiếp với hệ điều hành, hệ thống tệp tin, phần cứng cũng nhƣ camera thông qua một thƣ viện gọi là HighGUI – giao tiếp ngƣời dùng đồ họa mức cao. HighGUI cho phép chúng ta mở các cửa sổ, hiển thị ảnh, đọc và ghi các tệp tin liên quan tới ảnh, video cũng nhƣ điều khiển chuột, con trỏ và các sự kiện bàn phím. Thƣ viện HighGUI của

OpenCV có thể chia ra làm 3 phần: phần cứng, hệ thống file, và phần giao diện ngƣời dùng đồ họa.

Phần liên quan tới phần cứng thƣờng liên quan tới camera. Trong hầu hết các hệ hiều hành, thì việc tƣơng tác với camera là một công việc không mấy thích thú. HighGUI cung cấp một cách dễ dàng để truy xuất và lấy ra ảnh cuối cùng thu đƣợc, ẩn đi các công việc nhàm chán cần thiết phải làm. Phần hệ thống file thì thƣờng liên quan tới việc nạp và lƣu trữ các ảnh. Một đặc điểm khá thú vị của thƣ viện này là cho phép chúng ta đọc các đoạn video với cùng phƣơng thức giống nhƣ trực tiếp từ camera. Chính vì vậy, chúng ta có thể tạm quên đi các công việc liên quan tới phần cứng. Cũng với cùng một tinh thần đó, HighGUI cũng cấp cho chúng ta các hàm để nạp và lƣu trữ ảnh. Căn cứ vào cấu trúc tệp ảnh lƣu đƣợc lƣu trữ, nó có thể tự xác định cách mã hóa và giải mãi thích hợp với cấu trúc ảnh đó. Và phần cuối cùng là giao diện ngƣời dùng đồ họa. Thƣ viện này cũng cấp các hàm cho phép chúng ta mở một cửa sổ mới và hiển thị các ảnh một cách dễ dàng. Không chỉ có vậy, chúng ta có thể đang ký và nhận các đáp ứng trả về cho các sự kiện chuột và bàn phím thao tác trên cửa sổ đó. Đây là một việc không phải dễ dàng với các ứng dụng cơ bản. Hay chúng ta cũng có thể sử dụng các thanh trƣợt để điều chỉnh các giá trị cho chƣơng trình, thời gian hiển thị đoạn video,…

Trƣớc khi có thể hiển thị một ảnh trên màn hình sử dụng HighGUI thì chúng ta cần thiết lập cửa sổ hiển thị bằng lời gọi cvNamedWindow(). Hàm này nhận 2 tham số lối vào là tên cửa số vả một giá trị cờ. Tên cửa sổ đƣợc dùng để hiển thị trên dòng tiêu đề, để điều khiển các thông điệp cửa sổ cũng nhƣ đƣợc truyền cho các hàm HighGUI khác. Giá trị cờ xác định rằng cửa sổ có tự động co giãn kích thƣớc cho vừa với bức ảnh hiển thị trong nó hay không. Và đây là mô tả nguyên mẫu hàm cụ thể nhƣ sau

int cvNamedWindow( const char* name,

int flags = CV_WINDOW_AUTOSIZE );

Sau khi đã sử dụng xong cửa sổ, ta có thể giải phóng nó bằng lời gọi cvDestroyWindow() với tham số là tên cửa sổ giống nhƣ trong phần thiết lập. Trong OpenCV, các cửa sổ đƣợc tham chiếu đến thông qua tên cửa sổ thay vì các điều khiển kém thân thiện hơn nhƣ là các biến tham chiếu mà có thể khác

nhau giữa các hệ điều hành. Đây cũng là một ƣu điểm lớn của OpenCV đối với các nhà nghiên cứu, những ngƣời sử dụng nó.

Muốn hiện thị đƣợc ảnh thì trƣớc đó chúng ta phải đọc nó từ tệp tin bằng lời gọi:

IplImage* cvLoadImage( const char* filename,

int iscolor = CV_LOAD_IMAGE_COLOR );

Khi mở một ảnh, cvLoadImage() không quan tâm tới phần mở rộng của tệp tin – vì nó có thể bị thay đổi một cách dễ dàng. Thay vào đó, nó sẽ căn cứ vào các byte mã hóa đầu tiên để biết đƣợc bộ mã hóa-giải mã thích hợp để sử dụng. Tham số thứ hai xác định cách thức nạp ảnh vào IplImage, cụ thể nhƣ sau:

Giá trị Ý nghĩa

CV_LOAD_IMAGE_COLOR (giá trị mặc định)

Nạp ảnh 3 kênh với mã hóa 8 bit cho mỗi kênh. Nội dung ảnh có thể đƣợc biến đổi sao cho phù hợp với giá trị trả về.

CV_LOAD_IMAGE_ANYDEPTH Nạp ảnh không phải 8 bit

CV_LOAD_IMAGE_GRAYSCALE Tự động biến đổi ảnh về dạng mức xám 1 kênh

CV_LOAD_IMAGE_ANYCOLOR Nạp ảnh từ tệp ảnh

CV_LOAD_IMAGE_UNCHANGED Nạp ảnh đúng với cấu trúc đƣợc định nghĩa trong tệp tin

Để lƣu trữ ảnh sau khi đã xử lý xong ta có thể sử dụng hàm sau: int cvSaveImage(

const char* filename, const CvArr* image

);

Bây giờ chúng ta đã sẵn sàng để có thể hiện thị ảnh đọc từ tệp ảnh và hiển thị trên cửa sổ đƣợc thiết lập ở phần trƣớc chỉ bằng lời gọi hàm khá đơn giản:

void cvShowImage( const char* name, const CvArr* image );

Tham số đầu tiên là tên cửa sổ cần vẽ. Tiếp đó là ảnh cần hiển thị. Ta có thể lấy một ví dụ đơn giản về việc lấy tên tệp từ dòng lệnh, tạo ra một cửa sổ sau đó hiển thị ảnh từ tệp đó lên màn hình.

int main(int argc, char** argv){

cvNamedWindow( argv[1], 1 );

IplImage* img = cvLoadImage( argv[1] ); cvShowImage( argv[1], img );

while( 1 ) {

if( cvWaitKey( 100 ) == 27 ) break; }

cvDestroyWindow( argv[1] ); cvReleaseImage( &img ); }

Khi làm việc với video, chúng ta cần quan tâm tới một số các hàm nhƣ đọc/ghi tệp video, lấy ảnh từ camera, hiển thị trên màn hình,.. CvCapture là cấu trúc chứa các thông tin cần thiết cho việc đọc các khung hình từ camera hay tệp video. Tùy thuộc vào tệp nguồn mà chúng ta sử dụng hai lời gọi khác nhau để tạo và thiết lập cấu trúc CvCapture là:

CvCapture* cvCreateFileCapture( const char* filename ); CvCapture* cvCreateCameraCapture( int index );

Trong trƣờng hợp cvCreateFileCapture(), chúng ta chỉ đơn giản là truyền vào tên tệp tin MPG hay AVI và OpenCV sẽ mở và thiết lập để sẵn sàng đọc nó. Nếu việc mở thành công thì chúng ta có thể bắt đầu nhận các khung hình thông qua một con trỏ trả về kiểu CvCapture. Đồng nghĩa với đó nếu giá trị con trỏ trả về là NULL thì việc mở tệp thất bại; có thể do tệp không tồn tại hay bộ giải mã không phù hợp,… Hàm cvCreateCameraCapture() làm việc khác giống với cvCreateFileCapture() trừ việc không phải quan tâm tới bộ mã hóa/giải mã video. Một giá trị truyền vào mô tả thiết bị nào sẽ đƣợc sử dụng.

Thông qua một con trỏ CvCapture hợp lệ, chúng ta có thể lấy các khung hình. Có 2 cách để làm điều này: Một là gọi cvGrabFrame() với tham số là con trỏ CvCapture và kết quả trả về là một số nguyên. Số nguyên đó bằng 1 tức là việc lấy khung hình là thành công còn 0 là không thành công. Chú ý là hàm này chỉ kiểm tra trạng thái lấy đƣợc khung hình còn ảnh thu đƣợc sẽ đƣợc lƣu vào bộ nhớ đệm mà chúng ta không truy nhập đƣợc. Chính vì vậy, sau lời gọi cvGrabFrame(), chúng ta sẽ gọi cvRetrieveFrame() để lấy về giá trị bộ đệm chứa ảnh đƣợc lƣu trong bộ đệm có nội dung khung hình trƣớc đó nhƣng lƣu trữ ở một vị trí khác để không bị khung hình mới đè lên. Cách thức hai, chúng ta có thể sử dụng hàm cvQueryFrame() nhƣ là sự kết hợp giữa cvGrabFrame() và cvRetrieveFrame().

Sau khi đã làm việc xong với camera, chúng ta nên ngắt kết nối bằng lời gọi cvReleaseCapture()

void cvReleaseCapture( CvCapture** capture );

Có rất nhiều các thuộc tính trong cấu trúc CvCapture, để có thể lấy và thiết lập thì chúng ta có thể sử dụng hàm sau: double cvGetCaptureProperty( CvCapture* capture, int property_id ); int cvSetCaptureProperty( CvCapture* capture, int property_id,

double value );

Trong đó, capture là con trỏ tới CvCapture đang sử dụng; property_id là thông số cần lấy thông tin bao gồm:

Tên Ý nghĩa

CV_CAP_PROP_POS_FRAME Vị trí tính theo số thứ tự của khung hình hiện tại

CV_CAP_PROP_POS_AVI_RATIO Giá trị từ 0..1 biểu diễn vị trí của khung hình

CV_CAP_PROP_POS_MSEC Vị trí tính theo thời gian(ms) của khung hình hiện tại

CV_CAP_PROP_FRAME_WIDTH Độ rộng khung hình CV_CAP_PROP_FRAME_HEIGHT Chiều cao khung hình

CV_CAP_PROP_FPS Số khung hình/giây

CV_CAP_PROP_FOURCC Mô tả bộ mã hóa/giải mã video CV_CAP_PROP_FRAME_COUNT Tổng số khung hình

Để lƣu trữ đoạn video, chúng ta có thể thực hiện dễ dàng không qua các lời gọi hàm sau:

CvVideoWriter* cvCreateVideoWriter( const char* filename,

int fourcc, double fps,

CvSize frame_size, int is_color = 1 );

int cvWriteFrame(

CvVideoWriter* writer, const IplImage* image );

void cvReleaseVideoWriter( CvVideoWriter** writer );

Một phần của tài liệu Thuật toán phát hiện chuyển động (Trang 55)