OpenCV cung cấp các hàm vẽ cơ bản như vẽ điểm, vẽ đường thẳng, đường tròn, elip, hình chữ nhật, text,… Mục đích là khi nhận dạng hoặc phát hiện được đối tượng thì vẽ lên ảnh output cho dễ nhìn
Đường tròn khác với hình tròn, đường chữ nhật khác với hình chữ nhật,… Thí dụ:
– Đường tròn chỉ là tập hợp các điểm cách tâm một khoảng bằng bán kính r
– Hình tròn là tập hợp tất cả các điểm có khoảng cách bằng hoặc nhỏ hơn bán kính r
Vẽ điểm
Vẽ điểm hay là set giá trị màu cho 1 điểm nào đó. (Hơi khó nhìn 1 tí)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ màu đỏ tại điểm có tọa độ (100;100) img.at<cv::Vec3b>(100, 100) = cv::Vec3b(0, 0, 255); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ đường thẳng
Đường thẳng được xác định bởi 2 điểm. Ngoài ra được xác định thêm bởi các thông số như màu, nét đậm/nhạt, kiểu đường thẳng.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ đường thẳng màu đỏ nối 2 điểm có tọa độ (100;100) và (200;100), với nét đậm bằng 1 cv::line(img, cv::Point(100, 100), cv::Point(200, 100), cv::Scalar(0, 0, 255), 1); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ đường tròn
Đường tròn được xác định bởi tâm đường tròn và bán kính.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ đường tròn màu đỏ có tâm (200;150) và bán kính bằng 50, nét đậm bằng 1 cv::circle(img, cv::Point(200, 150), 50, cv::Scalar(0, 0, 255), 1); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ hìnhtròn
Tương tự như vẽ đường tròn nhưng có fill màu bên trong, chỉ khác tham số là nét đậm nhạt bằng -1
1 2 |
//vẽ hìnhtròn màu đỏ có tâm (200;150) và bán kính bằng 50, nét đậm bằng -1 cv::circle(img, cv::Point(200, 150), 50, cv::Scalar(0, 0, 255), -1); |
Vẽ đường elip
Đường elip được xác định bởi tâm elip và 2 trục. Có 2 cách vẽ:
– Truyền tham số bao gồm: kích cỡ, góc xoay của elip, điểm bắt đầu và điểm kết thúc
– Truyền tham số là hình chữ nhật bao lấy đường elip, có nghĩa là đường elip ngoại tiếp hình chữ nhật
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ đường elip màu đỏ có tâm (200;150), trục nhỏ bằng 50 và trục lớn bằng 80 double angle = 90; double startAngle = 90; double endAngle = 270; cv::ellipse(img, cv::Point(200, 150), cv::Size(25, 40), angle, startAngle, endAngle, cv::Scalar(0, 0, 255), 1); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ hình elip
Tương tự như vẽ đường elip nhưng có fill màu bên trong, chỉ khác tham số là nét đậm nhạt bằng -1
1 |
cv::ellipse(img, cv::Point(200, 150), cv::Size(25, 40), angle, startAngle, endAngle, cv::Scalar(0, 0, 255), -1); |
Vẽ đường chữ nhật
Vẽ đường chữ nhật cũng có 2 cách vẽ:
– Truyền tham số là hình chữ nhật cần vẽ (cv::Rect)
– Truyền điểm góc trên-trái và góc dưới-phải
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ đường chữ nhật có điểm bắt đầu là (50,50) và kích thước là 200 x 100px cv::rectangle(img, cv::Rect(50, 50, 200, 100), cv::Scalar(0, 0, 255), 1); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ hình chữ nhật
Tương tự như vẽ đường chữ nhật nhưng có fill màu bên trong, chỉ khác tham số là nét đậm nhạt bằng -1
1 |
cv::rectangle(img, cv::Rect(50, 50, 200, 100), cv::Scalar(0, 0, 255), -1); |
Vẽ text
OpenCV cung cấp nhiều loại font để vẽ, code bên dưới vẽ ra tất cả font
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(500, 600, CV_8UC3); img = cv::Scalar(0, 0, 0); //vẽ text lên ảnh cv::putText(img, "FONT_HERSHEY_COMPLEX", cv::Point(0, 50), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_COMPLEX_SMALL", cv::Point(0, 100), cv::FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_DUPLEX", cv::Point(0, 150), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_PLAIN", cv::Point(0, 200), cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_SCRIPT_COMPLEX", cv::Point(0, 250), cv::FONT_HERSHEY_SCRIPT_COMPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_SCRIPT_SIMPLEX", cv::Point(0, 300), cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_SIMPLEX", cv::Point(0, 350), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_HERSHEY_TRIPLEX", cv::Point(0, 400), cv::FONT_HERSHEY_TRIPLEX, 1, cv::Scalar(255, 0, 0), 2); cv::putText(img, "FONT_ITALIC", cv::Point(0, 450), cv::FONT_ITALIC, 1, cv::Scalar(255, 0, 0), 2); //hiển thị ảnh cv::imshow("Font", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Vẽ đường gấp khúc
Để vẽ đường gấp khúc các bạn truyền vào danh sách các điểm cần vẽ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
void main() { //tạo ảnh màu black với kích thước 400 x 300 pixels cv::Mat img = cv::Mat(300, 400, CV_8UC3); img = cv::Scalar(0, 0, 0); //tạo danh sách các điểm vector<cv::Point> contour; contour.push_back(cv::Point(50, 50)); contour.push_back(cv::Point(100, 100)); contour.push_back(cv::Point(150, 50)); contour.push_back(cv::Point(200, 100)); contour.push_back(cv::Point(250, 50)); contour.push_back(cv::Point(300, 100)); const cv::Point *pts = (const cv::Point*) cv::Mat(contour).data; int npts = contour.size(); //vẽ các điểm bool closed = true; cv::polylines(img, &pts, &npts, 1, closed, cv::Scalar(0, 0, 255), 1); //hiển thị ảnh cv::imshow("Image", img); cv::waitKey(0); // Wait for a keystroke in the window getchar(); } |
Ví dụ: vẽ lồng đèn ngôi sao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
void main() { cv::Mat img = cv::Mat::zeros(400, 400, CV_8UC3); cv::Mat img2 = cv::Mat::zeros(400, 400, CV_8UC3); int r = 180; cv::circle(img, cv::Point(200, 200), r, cv::Scalar(255, 255, 255)); cv::circle(img2, cv::Point(200, 200), r, cv::Scalar(255, 255, 255), 1, CV_AA); std::vector<cv::Point> contour; contour.push_back(cv::Point(200, 24)); contour.push_back(cv::Point(97, 344)); contour.push_back(cv::Point(370, 147)); contour.push_back(cv::Point(31, 148)); contour.push_back(cv::Point(304, 344)); const cv::Point *pts = (const cv::Point*) cv::Mat(contour).data; int npts = contour.size(); bool closed = true; cv::polylines(img, &pts, &npts, 1, closed, cv::Scalar(0, 0, 255), 1); cv::polylines(img2, &pts, &npts, 1, closed, cv::Scalar(0, 0, 255), 1, CV_AA); cv::imshow("Star", img); cv::imshow("Star AA", img2); } |
Khử răng cưa
Ở ví dụ trên có tham số CV_AA, nghĩa là Anti Alias, có thể thấy kết quả khác nhau rõ rệt của 2 hình. Bên dưới là text khác nhau về không khử và khử răng cưa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int main(int argc, char** argv) { cv::Mat img = cv::Mat::zeros(100, 400, CV_8UC3); cv::Mat img2 = cv::Mat::zeros(400, 400, CV_8UC3); cv::putText(img, "thi giac may tinh", cv::Point(10, 40), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 255, 255), 1); cv::putText(img, "thi giac may tinh", cv::Point(10, 80), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 255, 255), 1, CV_AA); cv::imshow("Text", img); cv::waitKey(); getchar(); return 0; } |