Một vài vấn đề trong lập trình với OpenCV

Ngày 05/06/2015:

Ngày 04/06/2015, sau hơn 6 tháng kể từ bản beta, phiên bản chính thức OpenCV 3.0.0 đã được đưa ra với rất nhiều cải tiến. Bên cạnh đó bản TBB 4.3 update 5 cũng được MS cập nhật. Boost 1.5.8 cũng mới được cập nhật trong thời gian gần đây.

Ngày 13/11/2014:

Bản OpenCV 3.0-Beta đã được đưa ra sau nhiều cải tiến. Bên cạnh đó bản cập nhật IPP 8.2.1 và TBB 4.3.1 cũng được cập nhật. Microsoft cũng đã tung ra bản update 4 cho Visual Studio 2013 và bản Preview cho VS 2015. Boost 1.5.7 cũng mới được cập nhật trong thời gian gần đây. Qủa là một ngày với nhiều cập nhật.

Ngày 22/08/2014:

Với rất nhiều các tính năng mới và một giao diện (API) C++ gần như triệt để (các hàm hỗ trợ C với tiếp đầu ngữ cv, chẳng hạn như cvCopyImage, cvFillImage đã bị loại bỏ và số còn lại thì ngày càng ít đi), bản OpenCV 3.0 Alpha đã được đưa ra. Có thể xem thêm về các tính năng mới của bản alpha này ở đây và ở đây.  Link download.

Ngày 16/08/2014:

Bản OpenCV 3.0.0 dev-version mới nhất với các tính năng sau:

+ Hỗ trợ OpenCL mạnh hơn (nhiều hàm được cài đặt với OpenCL kernel hơn). Nền tảng OpenCL được mặc định sử dụng, nếu hệ thống không hỗ trợ, có thể có báo lỗi.

+ Nhanh hơn với thư viện IPP của Intel, hầu hếtcác thao tác đều nhanh hơn (xem chi tiết ở đây), chưa phát hiện hàm nào chậm hơn.

+ Module highgui được chia thành 2: videoio and highgui.

+ Sửa lỗi khi build module cudaoptflow.

+ Cập nhật với bản cmake 3.

+ Một số applications bị bỏ đi, chỉ còn một application là traincascade.

Ngày 21/07/2014:

Một địa chỉ với nhiều ví dụ theo kiểu “Learn by examples” về OpenCV: http://opencvexamples.blogspot.com/.

TBB 4.2 update 5.

Ngày 3/03/2014:

Forum cho các hỏi đáp về các vấn đề về lập trình với OpenCV (thực sự rất có ích): OpenCV Q&A forum.

Ngày 13/01/2014:

Update 3 of TBB 4.2: Hôm nay bản Update 3 của thư viện TBB 4.2 đã được tung ra. Đối với những ai muốn tối ưu tốc độ của thư viện OpenCV, thì TBB là một giải pháp khá tốt, bên cạnh các giải pháp khác như SSE2, WinThread hoặc C++11 thread. Có thể download bản TBB 4.2 update 3 ở địa chỉ này, xem các thay đổi từ bản Update 2 lên Update 3 ở đây.

Ngày 07/12/2013:

Một số nguồn, tài liệu có ích cho những người mới bắt đầu với OpenCV.

+ OpenCV 2.4.8 reference manual. Tài liệu về version mới nhất của OpenCV giúp tra cứu các hàm thư viện của OpenCV theo từng mục tương ứng với các file thư viện khác nhau như: core, imgproc, highgui, video …

+ OpenCV Tutorial 2.4.3: http://docs.opencv.org/opencv_tutorials.pdf. Hướng dẫn chi tiết về cấu hình với công cụ (VS, Eclipse), nền tảng (Windows, Linux, Adroid, iOS) và ngôn ngữ khác nhau (C++, Java). Thêm vào đó là khá nhiều ví dụ đơn giản, ngắn gọn.

http://opencv-srf.blogspot.fr/. Một Tutorial khác, cũng khá dễ hiểu.

Ngày 28/08/2013:

GUI application with OpenCV: để tạo một ứng dụng giao diện đồ họa sử dụng OpenCV có một số lựa chọn: dùng MFC, Qt, hoặc wxWidgets. Tuy nhiên Qt chiếm ưu thế hơn vì:

+ MFC đang bị MS đưa vào dạng cần loại bỏ

+ MFC chỉ chạy với Windows

+ wxWidgets không tiện và mạnh như Qt

+ Ứng dụng Qt có thể dễ dàng compile lại để chạy trên các hệ thống Windows hoặc Linux

Một số ví dụ cơ bản về tạo ứng dụng GUI sử dụng Qt với OpenCV:

link 1 – Hiển thị ảnh đơn giản

link 2 – Đa luồng và một số thao tác lọc ảnh

link 3 – Thao tác với webcam

Ngày 03/06/2013:

Xử lý ảnh xám (grayscale image processing). Theo mặc định khi hàm imread() hoặc cvLoadImage() đọc 1 ảnh (từ file hoặc một frame video), ảnh nhận được (Mat hoặc IplImage) sẽ có 3 channel cho ba màu Blue, Green, Red (theo đúng thứ tự). Tuy nhiên việc xử lý ảnh thường dựa trên ảnh xám (một channel, với giá trị điểm ảnh, hay cường độ sáng – intensity, dao động từ 0 tới 255) nên điều quan trọng đầu tiên là cần chuyển một ảnh đọc được về ảnh xám 1 channel, để thực hiện điều này ta làm như sau:

Mat im = imread(<file path>);
if(im.type()!=CV_8UC1)
	cvtColor(im, im, CV_BGR2GRAY);

Tiếp đến do các thao tác xử lý dựa trên điểm ảnh cần làm việc với các giá trị kiểu số thực nên ta cần chuyển tiếp các điểm ảnh về kiểu CV_32F hoặc CV_64F như sau:

im.convertTo(im,CV_32F);

Chú ý là thao tác này (chuyển thành ảnh xám 1 channel) là rất quan trọng vì nhiều hàm xử lý của OpenCV chỉ làm việc với dữ liệu ảnh (Mat) 1 channel, chẳng hạn như minMaxLoc(), compare().

Tất nhiên ta cũng có thể tách các channel của một ảnh hoặc hợp lại từ 3 channel bằng các hàm split() và merge(), ví dụ:

Mat im = imread(<file path>);
vector<Mat> rgb; 
split(in, rgb);

Mat color;

split(rgb, color);

Để truy cập vào một điểm ảnh ở hàng i cột j ta cùng cú pháp: im.at<float>(i,j) cho ảnh CV_32F và  im.at<double>(i,j) cho ảnh CV_64F.

Lấy giá trị mức xám lớn nhất (max) và nhỏ nhất (min) của một ảnh:

Mat im=imread(<file path>);

if(im.type()!=CV_8UC1)
	cvtColor(im, im, CV_BGR2GRAY);
double max_val, min_val; 
minMaxIdx(im, &min_val, &max_val, 0, 0); 
cout << "Max=" << max_val << ", Min=" << min_val << endl;

Ngày 30/05/2013:

1. Đọc/ghi file ảnh. Dữ liệu cho một chương trình xử lý ảnh là ảnh thu nhận từ các thiết bị ghi, thường được lưu dưới dạng file ảnh hoặc file video với các format khác nhau. Về cơ bản, OpenCV hỗ trợ đọc hầu hết các format ảnh phổ biến (.png, .jpg, .bmp, …), còn về format video thì trên hệ thống có codec nào, OpenCV có thể đọc được format đó, tuy nhiên phổ biến nhất là các file .avi. Hàm đọc file ảnh có 2 loại, một dành cho chương trình viết theo dạng C (sử dụng cấu trúc IplImage) và loại thứ hai dành cho các chương trình viết theo kiểu C++ (dùng lớp Mat), cụ thể như sau:

IplImage * img = cvLoadImage(<file path>);

Mat img = imread(<file path>);

Tương ứng là hai hàm dùng để ghi file ảnh:

cvSaveImage(<file path>, img ); // cho IplImage * img;

imwrite(<file path>, img); // cho Mat img;

Để đọc các frame của một file video hoặc từ một webcam có thể dùng cấu trúc CvCapture (khi đó ảnh đọc sẽ có kiểu là IplImage) hoặc VideoCapture (khi đó ảnh đọc sẽ là đối tượng của lớp Mat). Nói chung OpenCV không phân biệt ảnh được đọc từ file hay trực tiếp từ webcam (Bravo OpenCV!). Ban đầu là thao tác khởi tạo:

CvCapture* capture=0;
IplImage* frame=0;

capture = cvCaptureFromAVI(<file path>); // from file

capture = cvCaptureFromCAM(0); // from webcam

// đọc các frame tiếp theo

frame = cvQueryFrame( capture );

VideoCapture capture;

Mat frame;

capture.open(<file path>); // open file

capture.open(0); // open webcam device

// đọc các frame

capture >> frame;

Sau đây là một ví dụ đơn giản về đọc file .avi và hiển thị lên màn hình:

#include <opencv2\opencv.hpp>
#include <opencv2\core.hpp>
#include <opencv2\highgui.hpp>
#include <opencv2\imgproc.hpp>
using namespace cv;
int main(int argc, char** argv)
{
	CvCapture* capture=0;
	IplImage* frame=0;
	capture = cvCaptureFromAVI(argv[1]); // read AVI video
	if( !capture )
		throw "Error when reading steam_avi";

	cvNamedWindow( "w", 1);
	for(;;)
	{
		frame = cvQueryFrame( capture );
		if(!frame)
			break;
		cvShowImage("w", frame);

		cvWaitKey(10);
		if(cvWaitKey(30) >= 0)
			break;
	}
	cvReleaseImage(&frame);
	cvReleaseCapture( &capture );
	cvDestroyWindow("w");

	return 0;
}

Còn đây là một ví dụ với C++:

#include <opencv2\opencv.hpp>
#include <opencv2\core.hpp>
#include <opencv2\highgui.hpp>
#include <opencv2\highgui\highgui_c.h>
#include <opencv2\imgproc\imgproc_c.h>
//#include <iostream>
//using namespace std;
using namespace cv;
int main(int argc, char ** argv)
{
	VideoCapture capture;
	Mat frame;
	capture.open(argv[1]);
	if(!capture.isOpened())
		return 1;
	while(1)
	{
		capture >> frame;
		if(frame.empty())
			break;
		imshow("w", frame);
		cvWaitKey(10);
		if(cvWaitKey(30) >= 0)
			break;
	}
	return 0;
}

Xem thêm các ví dụ và chi tiết khác tại:

http://www.grandmaster.nu/blog/?page_id=49

http://docs.opencv.org/doc/tutorials/highgui/video-write/video-write.html

http://bsd-noobz.com/opencv-guide/40-4-display-video-from-file-camera

http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html

Ngày 23/05/2013:

1. Chuyển đổi kiểu giữa IplImage * (kết quả đọc ảnh bằng hàm cvLoadImage(), là một cấu trúc theo kiểu C) và Mat (một kiểu dữ liệu mới từ OpenCV 2, kết quả của hàm imread()) dùng hàm cvarrToMat():

IplImage * img = cvLoadImage(<file path>);

Mat mat = cvarrToMat(img);

cvShowImage(“Using IplImage”, img);

imshow(“Using Mat”, mat);

Kiểu dữ liệu Mat của OpenCV (thực chất là một class của C++) hay được dùng vì có nhiều thao tác dựa trên cấu trúc ma trận của nó. Để chuyển ngược lại thì đơn giản hơn:

Mat mat = imread(<file path>);

IplImage img = mat;

2. OpenCV và lập trình GPU

Để có thể lập trình GPU với thư viện OpenCV, ta cần hai file thư viện opencv_gpu (.lib và .dll). Do bản chính thức là 2.4.5 dành cho Windows không được dịch với GPU đầy đủ nên không chạy được các hàm GPU của OpenCV, khi đó cần build OpenCV from source để có thể dùng các hàm này. Xem hướng dẫn ở đây với bản OpenCV 2.4.9.

3. GpuMat và Mat

GpuMat là cấu trúc tương tự Mat nhưng được dùng để chạy trên GPU Device, ví dụ khi muốn đọc ảnh, chuyển dữ liệu ảnh lên GPU để thực hiện thao tác xử lý gì đó (lọc ảnh, trích chọn đặc trưng, DFT, FFT, Wavelets, convolution ..) ta dùng hàm upload, rồi gọi tới hàm xử lý, tiếp đến dùng hàm download để chuyển dữ liệu từ GPU device xuống Host Memory:

Mat img = imread(<file path>);

Mat result;

GpuMat d_img;

d_img.upload(img);

<gọi hàm trên GPU để xử lý ảnh>

d_img.download(result);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: