Lập trình OpenCV C++ Bài 8 : Vẽ hình học trong OpenCV – P1

Hi. chào các bạn.

Chúng ta tiếp tục bài học tiếp theo trong chủ đề : Lập trình OpenCV C++

Bài hôm nay chúng ta sẽ nghiên cứu về cách vẽ các hình học cơ bản trong OpenCV.

Về cơ bản opencv là thư viện xử lý ảnh, nhưng nó cũng là một thư viện có các hàm đồ họa cơ bản.

Chúng ta có thể sử dụng các hàm đồ họa đó để vẽ được các yếu tố hình học cơ bản,

phụ trợ cho các ý tưởng trong xử lý ảnh.

Ví dụ vẽ một hình vuông màu đỏ bao quanh đôi mắt của một cá nhân trong tấm ảnh chẳng hạn.

Ok chúng cùng bắt đầu thực hành.

Tôi sẽ chia sẻ với các bạn cách vẽ 5 hình học cơ bản đó là.

+ Vẽ một đường thẳng -> Draw Line

+ Vẽ một hình chữ nhật -> Draw Rectangle

+ Vẽ một hình tròn -> Draw circle

+ Vẽ một hình elipse -> DrawElipse

+ Vẽ một hình đa giác -> Draw polygon

 

Step 1: Tạo menu item chức năng.

Các bạn thấy, như mọi bài trước tôi đều tạo các icon trên toolbar để làm chức năng xử lý.

Nhưng bài này tôi sẽ thay đổi một chút cho khác biệt, tôi sẽ dùng menuitem để làm chức năng xử lý.

Như vậy các bạn học opencv những cũng có cơ hội làm quen,

thực hành, ôn luyện lại kỹ thuật lập trình windows MFC luôn

Về cơ bản một chức năng của phần mềm sẽ được thể hiện bởi 4 phương thức đó là:

Icon toolbar, menu item, phím tăt, và command.

Không phải phần mềm nào cũng có đủ cả 4, nhất là xử lý command.

Ok, các bạn hãy tạo các menuitem chức năng như sau đây.

 

Các bạn mở cửa sổ resource ra, và chọn mục menu, sau đó tìm đến menu như hình mô tả.

Lưu ý: IDR_MAINFRAME là menu khi chương trình chạy lần đầu tiên, mà chưa có view.

Khi các bạn tạo new một cửa sổ, tức là các bạn tạo view,

thì menu ở dưới nó được sử dụng, nên các bạn cần hiểu được điều này,

để thêm cho đúng và không phải thắc mắc.

Mở menu lên các bạn nhìn sang view bên phải, rồi thêm một menu mới vào thanh menu.

Sau khi đánh ten menu các bạn enter nó, rồi kéo nó vào trong, để menu help vẫn ở cuối cùng.

Bắt đầu thêm các menu item như sau:

Để xem được cái id của menu ra sao, các bạn có thể bấm vào menuitem chuột phải chọn properties,

 

Hoặc các bạn tích vào item EditId, toàn bộ menu sẽ thể hiện ở dạng id

để các bạn xem được các id của các menu item được tạo ra.

Muốn về chế độ cũ, các bạn chuột phải bỏ tích vào mục EditId là xong.

Ok đó là các tạo menuitem.

Step2 : Tạo các hàm xử lý sự kiện.

Về cơ bản hàm xử lý sự kiện cho menuitem hay các icon trên toolbar chẳng khác gì nhau

Bản chất chúng chỉ là một id và thể hiện theo nhiều các khách nhau.

Trong trường hợp này có một điểm khác một chút:

Đó là Draw là một tổ hợp nhiều chức năng vẽ từ line cho đến polygon

Chúng là các id có chỉ số tuần tự tăng dần, do khai báo liên tiếp nhau cùng thời điểm.

Vậy tôi không cần viết 5 hàm xử lý sự kiện cho từng chức năng.

Mà tôi sẽ chỉ viết một hàm xử lý sự kiện theo kiểu phạm vi từ A đến B, với đối số truyền vào là chỉ số ID

Tôi sẽ làm như sau:

 

 

Các bạn sẽ thấy, với một tổ hợp các chức năng tương tự nhau và có id tuần tự chúng ta có thể sử dụng 1 hàm chung.

Bên trong chúng ta sẽ switch id tương ứng và gọi đến các hàm xử lý logic tương ứng

Step 3: Chúng ta sẽ tiến hành vẽ yếu tố

Chúng ta sẽ chia thành hai part nhỏ, và đây là part 1, vẽ các line và circle.

Trước khi vẽ các bạn thực hiện như sau:

Chúng ta thấy rằng, vẽ hình học trên view của windows, thì view của windows trong chủ đề này có 2 dạng,

-> Một là view bình thường, chưa hề load ảnh, xuất hiện khi bấm vào chức năng new

-> View đã load ảnh.

Trường hợp view đã load ảnh thì không sao, nhưng trường hợp 1 khi view chưa load ảnh, thì biến m_mat của chúng ta sẽ chưa có dữ liệu.

Do đó các bạn thêm đoạn code sau đây vào, để đảm bảo trong trường hợp new một màn hình, m_mat luôn có dữ liệu

 

Ok, như vậy giờ thì dù bạn tạo mới windows hay load một tấm ảnh, việc vẽ vẫn ok

a. Vẽ line:

Các bạn viết một hàm vẽ line tại lớp document như sau: (các bạn lưu ý khởi tạo cả bên file header nhé)

 

Trước hết tôi viết một hàm riêng cho việc update view và xử lý lại bitmap gọi là hàm ImpShow

=-> Mục đích để đỡ trùng lặp code, viết lại nhiều lần.

Các bạn sau khi viết xong, có thể thay thế các đoạn code trước đây cho việc update view bằng hàm này cho code gọn nhẹ.

Phân tích hàm vẽ line.

– Đầu tiên tôi tạo ra một biến cv::Mat img để làm biến xử lý, và nó được lấy dữ liệu từ m_Mat hiện có.

– Tôi tạo ra 2 point có tọa độ tương ứng là ptStart (100, 100) và ptEnd(200, 400)

– Màu sắc thì các bạn lưu ý, nó hơi ngược một chút, sẽ là thứ tự B G R

– Độ dày line là = 2

– Kiểu line là cv::Line_8

Sau đó các bạn gọi hàm cv::line và truyền các đối số như hình vào

Sau đó các bạn gọi hàm này trong hàm xử lý sự kiện tại hàm mainframe như sau.

 

Các bạn build và chạy thử chương trình. Kết quả sẽ như sau

Ok đó là kết quả.

Các bạn lưu ý rằng, thực tế không ai xử lý điểm fixed cứng như ví dụ tôi vừa làm,

mà điểm vẽ line phải linh động do người dùng lựa chọn. Ví dụ nhập điểm, pick điểm

====> Và đây có thể là một bài tập cho các bạn.

Hãy xử lý vẽ line theo yêu nhập được 2 điểm từ một dialog, hoặc pick 2 điểm trên màn hình để vẽ ra một line.

 

b. Vẽ một đường tròn

Hàm xử lý đường tròn như sau:

Có một lưu ý trong vẽ đường tròn, đó là các bạn thấy ko có tham số bán kính

mà thay vào đó là một vùng bounding của hình tròn kích thước 100, 100

Tuy nhiên khi thực hiện trong các sản phẩm thực tế, tham số này gây khó hiểu cho người dùng.

Nên bài toán tối ưu là sẽ nhập vào là bán kinh hay đường kính, sau đó tính ra bounding của hình tròn.

===> Các bạn hãy thử xem

Kêt quả:

 

Một chú ý khác, nếu các bạn thay tham số thickness trong hàm vẽ đường tròn ở trên bằng hằng số cv::FILLED

Bạn sẽ có một hình tròn như sau:

 

Ok, bài hôm nay dừng ở đây, bài tiếp theo chúng ta sẽ vẽ các hình học còn lại.

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.