Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV

Giới thiệu về thư viện OpenCV

OpenCV (Open Source Computer Vision) là một thư viện mã nguồn mở về thị giác máy

với hơn 500 hàm và hơn 2500 các thuật toán đã đư ợc tối ưu về xử lý ảnh, và các vấn đề

liên quan tới thị giác máy. OpenCV được thiết kế một cách tối ưu, sử dụng tối đa sức

mạnh của các dòng chip đa lõi để thực hiện các phép tính toán trong thời gian thực,

nghĩa là tốc độ đáp ứng của nó có thể đủ nhanh cho các ứng dụng thông thường. OpenCV

là thư viện được thiết kế để chạy trên nhiều nền tảng khác nhau (cross-patform), nghĩa là

nó có thể chạy trên hệ điều hành Window, Linux, Mac, iOS Việc sử dụng thư viện

OpenCV tuân theo các quy định về sử dụng phần mềm mã nguồn mở BSD do đó bạn có

thể sử dụng thư viện này một cách miễn phí cho cả mục đích phi thương mại lẫn thương

mại.

Dự án về OpenCV được khởi động từ những năm 1999, đến năm 2000 nó được giới thiệu

trong một hội nghị của IEEE về các vấn đề trong thị giác máy và nhận dạng, tuy nhiên

bản OpenCV 1.0 mãi tới tận năm 2006 mới chính thức được công bố và năm 2008 bản 1.1

(pre-release) mới được ra đời. Tháng 10 năm 2009, bản OpenCV thế hệ thứ hai ra đời

(thường gọi là phiên bản 2.x), phiên bản này có giao diện của C++ (khác với phiên bản

trước có giao diện của C) và có khá nhiều điểm khác biệt so với phiện bản thứ nhất.

Thư viện OpenCV ban đầu được sự hỗ trợ từ Intel, sau đó được hỗ trợ bở Willow Garage,

một phòng thí nghiệm chuyên nghiên cứu về công nghệ robot. Cho đến nay, OpenCV vẫn

là thư viện mở, được phát triển bởi nguồn quỹ không lợi nhuận (none -profit foundation)

và được sự hưởng ứng rất lớn của cộng đồng.

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 1

Trang 1

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 2

Trang 2

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 3

Trang 3

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 4

Trang 4

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 5

Trang 5

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 6

Trang 6

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 7

Trang 7

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 8

Trang 8

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 9

Trang 9

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV trang 10

Trang 10

Tải về để xem bản đầy đủ

pdf 103 trang duykhanh 10320
Bạn đang xem 10 trang mẫu của tài liệu "Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV

Giáo trình Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
hư trên. Ta chia chương trình làm hai phần, một phần chứa các hàm xử
lý ảnh và một phần thuộc về giao diện MFC. Phần chứa các hàm xử lý ảnh được đặt tên là
lớp MyCamCore, nó bao gồm một file header định nghĩa giao diện hàm mycamcore.h và
một file cài đặt mycamcore.cpp. Cấu trúc của hai file này có dạng như sau:
Mycamcore.h:
#pragma once
#include 
class MyCamCore
{
public:
 MyCamCore(void);
 ~MyCamCore(void);
 void Gray(cv::Mat&, cv::Mat&);
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 92
 voidỨngInvert(cv::Mat& dụng xử lý ,ả nhcv::Mat&); trong thực tế với thư viện OpenCV
 void ToHSV(cv::Mat&, cv::Mat&);
 void Blur(cv::Mat&, cv::Mat&);
};
Và mycamcore.cpp:
#include "MyCamCore.h"
#include 
#include 
#include 
using namespace cv;
MyCamCore::MyCamCore(void)
{
}
MyCamCore::~MyCamCore(void)
{
}
void MyCamCore::Gray(Mat &src, Mat &dst)
{
 if(src.channels() != 1)
 cvtColor(src, dst, CV_BGR2GRAY);
 else
 dst = src;
}
void MyCamCore::Invert(Mat &src, Mat &dst)
{
}
void MyCamCore::ToHSV(Mat &src, Mat &dst)
{
}
void MyCamCore::Blur(Mat &src, Mat &dst)
{
}
}
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 93
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Cách cài đặt này là khá giống với cách cài đặt của chương trình xử lý ảnh đơn giản như
trên, nghĩa là cứ một ảnh đầu vào src thì qua phép xử lý sẽ cho ra một ảnh dst, tuy nhiên
có một số điểm khác đó là các hàm được cài đặt tối ưu hơn để giúp cho việc hiển thị video
có thể liên tục, không bị giật cục, chẳng hạn như với hàm invert. Hàm invert có tác dụng
làm đảo ngược các giái trị pixel ảnh, nghĩa là dst(x,y) = 255 – src(x,y). Để cài đặt hàm
này theo cách thông thường, ta phải duyệt qua tất cả các phần tử của các kênh màu và
thực hiện phép toán trên. Tuy nhiên cách tiếp cận tới các điểm ảnh trong một ảnh là tốn
khá nhiều thời gian và kết quả là tốn khá nhiều thời gian xử lý, làm cho video hiển thị lên
bị giật cục. Để khắc phục tình trạng này ta quy ảnh về ma trận và thực hiện phép toán trên
ma trận dst = matran(255) – src, với matran(255) là một ma trận có cùng kích thước và
giá tri tất cả các pixel toàn là 255. Vì OpenCV đã tối ưu hóa các phép tính trên ma trận
(như sử dụng cả block các ô nhơ của biến ma trận thay vì tiếp cận từng điểm, chia phép
toán thành nhiều tiều trình nhỏ song song ) nên phép thực hiện trên sẽ nhanh hơn rất
nhiều. Hàm invert bây giờ được cài đặt như sau:
void MyCamCore::Invert(Mat &src, Mat &dst)
{
 static Mat mask = 255*Mat::ones(src.rows, src.cols, CV_8UC1);
 std::vector src_bgr;
 std::vector dst_bgr;
 split(src, src_bgr);
 for(size_t i = 0; i < src_bgr.size(); ++i)
 {
 Mat temp = mask - src_bgr[i];
 dst_bgr.push_back(temp);
 }
 cv::merge(dst_bgr, dst);
}
Trong hàm trên, phép cộng trừ ma trận chỉ được thực hiên trên một kênh màu, nên đầu
tiên ta tách ảnh thành 3 kênh màu riêng biệt, sau khi thực hiện phép toán xong ta lại trôn
lẫn 3 kênh mày này vào.
Đối với phần giao diện của chương trình, ta thiết kế một giao diện trên Dialog như sau:
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 94
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
 Các button được đặt tên biến có dạng btn_rgb, btn_capture Video được hiển thị nhờ
hiển thị liên tiếp các frame ảnh lên một cửa sổ, cửu sổ này được lấy handle sau đó được
gán vào picture box giống như cách hiển thị ảnh trên giao diện MFC trong các ví dụ trước
đã nói. Lớp cài đặt giao diện và cũng là chương trình chính khi ch ạy là lớp CMyCam, lớp
này được khởi tạo mặc định khi ta tiến hành tạo chương trình và chọn Dialog base. Ta sẽ
thêm vào header MyCamDlg.h và file cài đặt MyCamDlg.cpp một số biến, một số hàm để
điều khiển chương trình. Header CMyCam.h sẽ có dạng như sau:
// MyCamDlg.h : header file
#pragma once
#include 
#include 
#include "MyCamCore.h"
#include "afxwin.h"
class CMyCamDlg : public CDialogEx
{
public:
 CMyCamDlg(CWnd* pParent = NULL);
 enum { IDD = IDD_MYCAM_DIALOG };
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 95
 enumỨng{RGB d ụ=ng 0, x GRAYử lý =ả nh1, trongINVERT th= 2,ực HSVtế v=ớ 3,i thư YCRCB vi ệ=n 4,OpenCV CANNY = 5,
 SOBEL = 6, BLUR = 7, NOISE = 8, ROT = 9, DIV = 10, DISTORT =
11};
protected:
 virtual void DoDataExchange(CDataExchange* pDX);
private:
 // Các biến, các hàm chức năng trong chương trình
 bool is_stoped;
 bool is_captured;
 int type;
 cv::Mat src;
 cv::Mat dst;
 double fps;
 std::string output_folder;
 cv::Size size;
 std::string video_file_name;
 std::string img_file_name;
 cv::VideoWriter writer;
 cv::VideoCapture capture;
 MyCamCore mycam;
 void Start();
 void InitAppearance();
 bool ReadConfig(std::string);
 std::string CreateFileName();
protected:
 HICON m_hIcon;
 // cac ham override
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 afx_msg void OnClose();
 DECLARE_MESSAGE_MAP()
public:
 // các button
 CButton btn_snapshot;
 CButton btn_capture;
 CButton btn_setting;
 CButton btn_rgb;
 CButton btn_gray;
 ...
 // Các hàm khi click vào button
 afx_msg void OnBnClickedSnapshot();
 afx_msg void OnBnClickedCapture();
 afx_msg void OnBnClickedSetting();
 afx_msg void OnBnClickedRgb();
 afx_msg void OnBnClickedGray();
 ...
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 96
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
};
 Các biến điều khiển của chương trình bao gồm is_stoped, is_captured, type  để nhằm
kiểm tra xem vòng lặp có tiếp tục được thực hiện hay không, button capture có được bấm
chưa hoặc thể hàm xử lý ảnh nào mà ta đang gọi  Một số hàm được cài đặt trong file
MyCamDlg.cpp như:
 Hàm void InitAppearance(): Hàm này có tác dụng cài đặt giao diện khởi tạo
 cho chương trình, mục đích là làm cho giao diện trở nên đẹp hơn bằng cách thêm
 các ảnh trang trí vào các button. Chẳng hạn như bốn button Snapshot, Capture,
 Open Folder, Setting được trang trí bằng các ảnh như sau:
 Trong MFC, để đặt một ảnh vào một button hay một Control nào đó ta có thể dùng
 hàm SetBitmap với đối số của hàm là một HBITMAP, như vậy ta có thể cài đặt
 hàm tạo ra giao diện trang trí InitAppearance như sau:
 void CMyCamDlg::InitAppearance()
 {
 HBITMAP snapshot_bmp = (HBITMAP)LoadImageA(0,
 "../MyCam/res/snapshot.bmp", IMAGE_BITMAP, 0, 0,
 LR_LOADFROMFILE);
 btn_snapshot.SetBitmap(snapshot_bmp);
 HBITMAP capture_bmp = (HBITMAP)LoadImageA(0,
 "../MyCam/res/capture.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 btn_capture.SetBitmap(capture_bmp);
 HBITMAP setting_bmp = (HBITMAP)LoadImageA(0,
 "../MyCam/res/setting.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 btn_setting.SetBitmap(setting_bmp);
 HBITMAP folder_bmp = (HBITMAP)LoadImageA(0,
 "../MyCam/res/folder.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 btn_folder.SetBitmap(folder_bmp);
 ...
 }
 Hàm bool ReadConfig(std::string) có tác dụng đọc file config của chương
 trình, file này chứa một số tham số như tốc độ hình trên giây (fps), folder chứa ảnh
 chụp hoặc video ghi vào (output_folder)  Ban đầu các tham số này chứa giá trị
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 97
 mặỨc đngịnh, d ụtuyng nhiên xử lýkhiả ngưnh ờtrongi dùng thđiềựu cch tỉếnhv ớbằing thư cách vi nhệnấ nOpenCV vào button Setting
 thì các tham số này sẽ được thay đổi và lưu lại trong file config, những lần chạy
 sau, các thông số đó sẽ được đọc và có giá trị là giá trị mà người dùng đã tủy chỉnh
 cho chúng, hàm này sẽ được gọi ngay khi chương trình được chạy, hàm cài đặt chủ
 yếu dựa vào các hàm chuẩn trong C++ có dạng như sau:
 bool CMyCamDlg::ReadConfig(std::string file_name)
 {
 std::ifstream ifs(file_name);
 if(!ifs) return false;
 std::vector lines;
 std::string line;
 while(ifs >> line)
 {
 lines.push_back(line);
 }
 if(lines.size() < 2) return false;
 fps = atof(lines.at(0).c_str());
 output_folder = lines.at(1);
 ifs.close();
 return true;
 }
 Hàm std::string CreateFileName() có tác dụng tạo ra một chuỗi tên khác nhau
 ở các thời điểm khác nhau nhằm mục đích đặt tên cho các file ảnh chụp hoặc file
 video quay. Để tạo ra được các chuỗi tên không bị trùng nhau, tốt nhất là ta lấy
 theo thời gian, như vậy ở mỗi thời điểm chỉ có duy nhất một tên được tạo ra. Nếu
 như ta nhấn vào nut Snapshot (chụp ảnh) ở thời điểm là 11 giờ 30 phút 10 giây thứ
 6 ngày 28 tháng 12 năm 2012 thì tên của file ảnh lưu lại sẽ là Fri Dec 28 11_30_10
 2012.jpg. Ý tưởng cho việc cài đặt hàm này là lấy thời gian của hệ thống, sau đó
 thay thế các kí tự hai chấm “:” của thời gian bằng kí tự gạch nối dưới “_” (vì kí tự
 hai chấm là không hợp lệ để đặt tên trong window):
 std::string CMyCamDlg::CreateFileName()
 {
 CreateDirectoryA(output_folder.c_str(), NULL);
 time_t rawtime;
 time(&rawtime);
 std::string t = (std::string)ctime(&rawtime);
 int pos = t.find(":");
 if(pos != t.npos)
 {
 t.replace(pos, 1, "_");
 t.replace(pos + 3, 1, "_");
 t.pop_back();
 }
 std::string path = output_folder + "/";
 return path + t;
 }
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 98
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
 14. Hàm void Start() là hàm chứa vòng lặp của có chức năng xử lý ảnh thu được từ
 webcam và hiển thị ảnh đã qua xử lý. Ảnh được xử lý như thế nào thì tùy vào biến
 số type. Hàm này sẽ được gọi ngay từ đầu chương trình sau khi các giao diện và
 các thông số đã được khởi tạo hết, biến is_stoped sẽ dung để kết thúc vòng lặp của
 hàm này, biến này được đặt giá trị là true khi chương trình kết thúc trong hàm
 OnClose(). Hàm Start được cài đặt như sau:
 void CMyCamDlg::Start()
 {
 if(!capture.isOpened()) return;
 size = cv::Size((int) capture.get(CV_CAP_PROP_FRAME_WIDTH),
 (int) capture.get(CV_CAP_PROP_FRAME_HEIGHT));
 while(!is_stoped)
 {
 capture >> src;
 switch(type)
 {
 case RGB :
 dst = src;
 break;
 case GRAY :
 mycam.Gray(src, dst);
 break;
 case INVERT:
 mycam.Invert(src, dst);
 break;
 case HSV :
 mycam.ToHSV(src, dst);
 break;
 case ... :
 ...
 break;
 default:
 dst = src;
 break;
 }
 cv::imshow("Video", dst);
 if(is_captured && writer.isOpened())
 writer << dst;
 cv::waitKey(1);
 }
 }
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 99
 15. ỨngCác dụ hàmng xdùngử lý đảểnhđiề utrong khiển thquáự trìnhc tế xvửớlýi thư video vi khiện clickOpenCV vào các button
 đều có chung một dòng lệnh và có dạng như sau (giả sử hàm khi click vào button
 btn_invert):
 void CMyCamDlg::OnBnClickedInvert()
 {
 type = INVERT;
 }
 16. Hàm khi click vào button Snapshot (chụp ảnh):
 void CMyCamDlg::OnBnClickedSnapshot()
 {
 img_file_name = CreateFileName() + ".jpg";
 std::vector p(2);
 p.at(0) = CV_IMWRITE_JPEG_QUALITY;
 p.at(1) = 90;
 if(!dst.empty())
 {
 cv::imwrite(img_file_name, dst, p);
 }
 }
 Hàm này có tác dụng lưu ảnh đã qua xử lý với tên file ảnh là tên chuỗi được tạo ra
 từ hàm CreateFileName như đã nói ở trên và định dạng là jpg.
 17. Hàm khi click vào button Capture (ghi hình)
 void CMyCamDlg::OnBnClickedCapture()
 {
 is_captured = !is_captured;
 if(is_captured)
 {
 video_file_name = CreateFileName() + ".avi";
 if(size.height > 0 && size.width > 0)
 writer = cv::VideoWriter(video_file_name,
 CV_FOURCC('X','V', 'I', 'D'),8, size, true);
 btn_capture.SetBitmap((HBITMAP)(LoadImageA(0,"../MyCam/res/
 stop.bmp",0, 0, 0, LR_LOADFROMFILE)));
 btn_snapshot.EnableWindow(false);
 btn_setting.EnableWindow(false);
 btn_folder.EnableWindow(false);
 }
 else
 {
 btn_capture.SetBitmap((HBITMAP)(LoadImageA(0,"../MyCam/res/
 capture.bmp",0, 0, 0, LR_LOADFROMFILE)));
 btn_snapshot.EnableWindow(true);
 btn_setting.EnableWindow(true);
 btn_folder.EnableWindow(true);
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 100
 Ứng dụngif (writer.isOpened())xử lý ảnh trong thực tế với thư viện OpenCV
 writer.release();
 }
 }
 Khi button Capture được nhấn, đối tượng writer sẽ được tạo mới với tên của file
 video được tạo ra từ hàm CreateFileName(), định dạng ta sử dụng ở đây là avi với
 codec là XVID, đồng thời trạng thái của chương trình cũng chuyển sang trạng thái
 ghi hình, nghĩa là button Capture bây giờ được thay bởi ảnh có tên lá Stop, các
 button khác như Snapshot, Open Folder, Setting sẽ bị vô hiệu hóa. Nếu button này
 được click lần thứ hai (khi quá trình ghi hình đang diễn ra) thì ta sẽ ngừng việc ghi
 video lại, hủy đối tượng writer và trạng thái chương trình trở về như ban đầu.
 18. Hàm khi click vào button Open Folder (mở folder chứa file ảnh file video):
 void CMyCamDlg::OnBnClickedFolder()
 {
 std::string str_command = "explorer.exe " + output_folder;
 const char *command = str_command.c_str();
 system(command);
 }
 Hàm này sẽ mở folder chứa chứa ảnh chụp và video được ghi lại bằng hàm
 sytem(command), trong đó command là một chuỗi kiểu char để gọi hàm
 explorer.exe với đối số là đường dẫn tới folder cần mở.
 19. Hàm khi click button Setting:
 void CMyCamDlg::OnBnClickedSetting()
 {
 Setting setting;
 is_stoped = true;
 setting.DoModal();
 fps = setting.Fps;
 output_folder = setting.OutputPath;
 if(fps <= 0) fps = 8;
 if(output_folder == "") output_folder = "..\\Output";
 std::ofstream ofs("config.txt");
 if(!ofs) return;
 ofs << fps <<std::endl;
 ofs << output_folder;
 ofs.flush();
 ofs.close();
 is_stoped = false;
 Start();
 }
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 101
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
 Hàm này sẽ mở ra một dialog để người dung đặt các giá trị cho chương trình như
 fps, output_folder (bạn đọc có thể để thêm vào một số thông số như điều chỉnh độ
 sang cho ảnh trong quá trình xử lý chẳng hạn) Kết quả sau phép cài đặt này
 được ghi vào file config và được sử dụng cho các lần chạy chương trình tiếp theo.
Sau đây là kết quả chạy chương trình với trường hợp tạo ra các hình đối xứng và ảnh âm
bản:
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 102
 Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Chương trình trên được cài đặt ở dạng đơn giản để tạo ra một chương trình có thể làm
việc với các video stream mà cụ thể ở đây là thu từ webcam. Trên một khía cạnh nào đó
nó giống với ý tưởng của chương trình Cyberlink YouCam khá nổi tiếng và đã được
thương mại hóa, tuy nhiên nó đơn giản hơn khá nhiều cả về chức năng lẫn giao diện. Bạn
đọc có thể tự phát triển thêm nhiều hàm, nhiều modul để tự tạo ra cho mình một chương
trình thực sự thú vị dựa trên những điều cơ bản nhất.
 ------------------------------Hết------------------------------
 Một số vấn đề dự kiến sẽ được thảo luận trong phần tới: Phát hiện - nhận dạng
 mặt người, nhận dạng chữ viết tay, theo dõi đối tượng (object tracking), camera
 calibration - sterio vision và tái tạo không gian 3D, robot vision – một sô vấn đề
 về việc áp dụng xử lý ảnh trong các kì thi robocon 
Tác giả: Nguyễn Văn Long – long.06clc@gmail.com Page 103

File đính kèm:

  • pdfgiao_trinh_ung_dung_xu_ly_anh_trong_thuc_te_voi_thu_vien_ope.pdf