Phần 7. Ghi chú trên hình ảnh sử dụng OpenCV

0
4369
annotation

Ghi chú trên hình ảnh và video được sử dụng với nhiều mục đích khác nhau và với OpenCV quá trình này trở nên đơn giản và dễ dàng hơn. Các thao tác này có thể được sử dụng để thực hiện các công việc sau:

– Thêm thông tin vào hình ảnh và video

– Vẽ các khung giới hạn xung quanh các đối tượng khi thực hiện bài toán phát hiện đối tượng

– Đánh dấu các điểm ảnh với các màu khác nhau để phân đoạn hình ảnh

Vì mỗi khung hình trong video được thể hiện dưới dạng hình ảnh nên khi đã biết cách ghi chú trên hình ảnh thì việc ghi chú trên video cũng sẽ gần như tương tự.

Bài viết gồm các nội dung chính sau:

1. Vẽ đường thẳng trên ảnh

2. Vẽ đường tròn trên ảnh

3. Vẽ hình tròn đè lên ảnh

4. Vẽ hình chữ nhật trên ảnh

5. Vẽ hình elip trên ảnh

6. Vẽ nửa hình elip trên ảnh

7. Viết chữ trên ảnh với các định dạng khác nhau

Trước hết tham khảo đoạn code mẫu dưới đây. Chi tiết từng dòng lệnh sẽ được giới thiệu ở từng phần cụ thể tiếp theo.

Python

# Import dependencies
import cv2
# Read Images
img = cv2.imread('sample.jpg')
# Display Image
cv2.imshow('Original Image',img)
cv2.waitKey(0)
# Print error message if image is null
if img is None:
    print('Could not read image')
# Draw line on image
imageLine = img.copy()
Draw the image from point A to B
pointA = (200,80)
pointB = (450,80)
cv2.line(imageLine, pointA, pointB, (255, 255, 0), thickness=3, lineType=cv2.LINE_AA)
cv2.imshow('Image Line', imageLine)
cv2.waitKey(0)

C++

// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;
int main()
{
    // Read Images
    Mat img = imread("sample.jpg");
    // Display Image
    imshow("Original Image", img);
    waitKey();
    // Print Error message if image is null
    if (img.empty())
        {
            cout << "Could not read image" << endl;
        }
    // Draw line on image
    Mat imageLine = img.clone();
    Point pointA(200,80);
    Point pointB(450,80);
    line(imageLine, pointA, pointB, Scalar(255, 255, 0), 3, 8, 0);
    imshow("Lined Image", imageLine);
    waitKey();
}

Mặc định ở đây bạn đã cài đặt OpenCV trên máy. Nếu chưa có thể truy cập các link sau để cài đặt OpenCV:

1. Cài đặt OpenCV trên Ubuntu

2. Cài đặt OpenCV trên Windows từ Source

3. Cài đặt OpenCV trên Windows sử dụng trình cài đặt

Đầu tiên cần khai báo thư viện OpenCV. Lưu ý là trong C++ thường sử dụng cv ::function () nhưng vì đã sử dụng namespace cv nên có thể truy cập trực tiếp vào các hàm của OpenCV mà không cần thêm cv:: vào trước tên hàm.

Python

# Import dependencies
import cv2

C++

// Import dependencies
#include <opencv2/opencv.hpp>
#include <iostream>
// Using namespaces to nullify use of c::function(); syntax and std::function(); syntax
using namespace std;
using namespace cv;

Trong đoạn code tiếp theo, sử dụng imread() để đọc hình ảnh và imshow() để hiển thị nó. Với C++ thì thêm một số bước so với Python. Bạn cần khởi tạo hàm main và xác định ma trận cho hình ảnh, trước khi sử dụng hàm imread() để đọc hình ảnh. Để hiển thị hình ảnh, sử dụng hàm imshow().

Python

# Read the image
img = cv2.imread('sample.jpg')
#Display the input image
cv2.imshow('Original Image',img)
cv2.waitKey(0)

C++

int main()
{
   // Read Image
   Mat img = imread("sample.jpg");
   // Display the Image
   imshow("Original Image", img);
   waitKey();
   // Print Error message if image is null
   if (img.empty())
       {
           cout << "Could not read image" << endl;
       }
Ảnh gốc

Góc trên cùng bên trái của hình ảnh tương ứng với gốc của hệ tọa độ XY có (x = 0, y = 0).

Tiếp theo, bài viết sẽ mô tả cách ghi chú hình ảnh, sử dụng các hàm vẽ khác nhau trong OpenCV. Mỗi hàm đi kèm với một số đối số tùy chọn. Để biết chi tiết về các hàm này, vui lòng tham khảo thêm các tài liệu OpenCV.

1. Vẽ đường thẳng trên ảnh

Đầu tiên tìm hiểu cách chú thích hình ảnh bằng một đường thẳng màu, sử dụng hàm line() trong OpenCV. Trước khi gọi hàm line() nên tạo một bản sao của hình ảnh gốc bằng cách sử dụng:

– Hàm copy() trong Python

– Hàm clone() trong C ++

Bản sao này sẽ đảm bảo rằng bất kỳ thay đổi nào bạn thực hiện đối với hình ảnh sẽ không ảnh hưởng đến hình ảnh gốc. Trong C++, trước tiên cần tạo một ma trận cho bản sao của hình ảnh gốc.

Cú pháp cho hàm line():

line(image, start_point, end_point, color, thickness)

– Đối số đầu tiên là hình ảnh cần chú thích.

– Hai đối số tiếp theo là điểm bắt đầu và điểm kết thúc của đường thẳng.

Vẽ một đường thẳng từ điểm A(x1, y1) đến điểm B (x2, y2), trong đó A và B là hai điểm bất kỳ trong hình. Góc trên cùng bên trái của hình ảnh sẽ là điểm gốc của hệ tọa độ xy.

– Trục x thể hiện hướng nằm ngang hoặc các cột của hình ảnh.

– Trục y thể hiện hướng dọc hoặc các hàng của hình ảnh.

Đoạn code dưới đây sẽ thực hiện các công việc sau:

– Chỉ định điểm bắt đầu và điểm kết thúc, để vẽ một đường dài 250 pixel theo chiều ngang trên hình ảnh.

– Chỉ định màu của nó là kết hợp xanh lam và xanh lục, và độ dày của nó được chỉ định là 3.

Python

#Make copy of the image
imageLine = img.copy()
# Draw the image from point A to B
pointA = (200,80)
pointB = (450,80)
cv2.line(imageLine, pointA, pointB, (255, 255, 0), thickness=3))
cv2.imshow('Image Line', imageLine)
cv2.waitKey(0)

C++

// Make copy of the image
   Mat imageLine = img.clone();
   // Draw the image from point A to B
   Point pointA(200,80);
   Point pointB(450,80);
   line(imageLine, PointA, PointB, Scalar(255, 255, 0), 3, 8, 0);
   imshow("Lined Image", line_image);
   waitKey();

Kết quả sẽ được hình sau:

2. Vẽ đường tròn trên ảnh

Để vẽ đường tròn ta sử dụng hàm circle(). Cú pháp của hàm như sau:

circle(image, center_coordinates, radius, color, thickness)

– Đối số đầu tiên là hình ảnh cần ghi chú

– Hai đối số tiếp theo xác định tọa độ tâm của hình tròn và bán kính của nó.

– Hai đối số cuối cùng chỉ định màu và độ dày của đường tròn.

Đoạn code dưới đây sẽ chú thích hình ảnh với một đường tròn màu đỏ xung quanh khuôn mặt của con chó. Sau đó sử dụng hàm imshow() để hiển thị hình ảnh kết quả.

Python

# Make a copy of image
imageCircle = img.copy()
# define the center of circle
circle_center = (415,190)
# define the radius of the circle
radius =100
#  Draw a circle using the circle() Function
cv2.circle(imageCircle, circle_center, radius, (0, 0, 255), thickness=3, lineType=cv2.LINE_AA) 
# Display the result
cv2.imshow("Image Circle",imageCircle)
cv2.waitKey(0)

C++

// Make a copy of image
   Mat circle_image = img.clone();
   // define the center of circle
   Point circle_center(415,190);
   // define the radius of circle
   int radius = 100;
   // Draw a circle using the circle() Function
   circle(circle_image, circle_center, radius, Scalar(0, 0, 255), 3, 8, 0);
   // Display the result
   imshow("Circle on Image", circle_image);
   waitKey();

3. Vẽ hình tròn trên ảnh

Để vẽ hình tròn chỉ cần thay đổi đối số độ dày thành -1. Cụ thể:

Python

# make a copy of the original image
imageFilledCircle = img.copy()
# define center of the circle 
circle_center = (415,190)
# define the radius of the circle
radius =100
# draw the filled circle on input image
cv2.circle(imageFilledCircle, circle_center, radius, (255, 0, 0), thickness=-1, lineType=cv2.LINE_AA)
# display the output image 
cv2.imshow('Image with Filled Circle',imageFilledCircle)
cv2.waitKey(0)

C++

// make a copy of the original image
   Mat Filled_circle_image = img.clone();
   // define the center of circle
   Point circle_center(415,190);
   // define the radius of the circle
   int radius = 100;
   //Draw a Filled Circle using the circle() Function
   circle(Filled_circle_image, circle_center, radius, Scalar(255, 0, 0), -1, 8, 0);
   // display the output image
   imshow("Circle on Image", circle_image);
   waitKey();

4. Vẽ hình chữ nhật trên ảnh

Thao tác ghi chú tiếp theo sẽ là vẽ một hình chữ nhật trên hình ảnh, bằng cách sử dụng hàm rectangle() trong OpenCV. Cú pháp của hàm như sau:

rectangle(image, start_point, end_point, color, thickness)

Trong hàm rectangle(), cần khai báo điểm bắt đầu (trên cùng bên trái) và điểm kết thúc (dưới cùng bên phải) cho các góc của hình chữ nhật. Đoạn code dưới đây sẽ vẽ một hình chữ nhật màu đỏ, trên khuôn mặt của con chó.

Python

# make a copy of the original image
imageRectangle = img.copy()
# define the starting and end points of the rectangle
start_point =(300,115)
end_point =(475,225)
# draw the rectangle
cv2.rectangle(imageRectangle, start_point, end_point, (0, 0, 255), thickness= 3, lineType=cv2.LINE_8) 
# display the output
cv2.imshow('imageRectangle', imageRectangle)
cv2.waitKey(0)

C++

// make a copy of the original image
   Mat rect_image = image.clone();
   // Define the starting and end points for the rectangle
   Point start_point(300,115);
   Point end_point(475,225);
   // Draw a rectangle using the rectangle() function
   rectangle(rect_image, start_point, end_point, Scalar(0,0,255), 3, 8, 0);
   imshow("Rectangle on Image", rect_image);
   waitKey();

5. Vẽ hình elip trên ảnh

Để vẽ hình elip ta sẽ sử dụng hàm ellipse(). Cú pháp của hàm này tương tự như vẽ hình tròn. Tuy nhiên thay vì khai báo bán kính, cần phải xác định các giá trị sau:

– Độ dài trục chính và trục nhỏ của elip

– Góc quay

– Góc bắt đầu và góc kết thúc của elip (những góc này cho phép ta có thể vẽ một phần của đường cong).

ellipse(image, centerCoordinates, axesLength, angle, startAngle, endAngle, color, thickness)

Đoạn code sau đây sẽ vẽ:

– Hình elip màu xanh nằm ngang

– Hình elip màu đỏ nằm dọc

Python

# make a copy of the original image
imageEllipse = img.copy()
# define the center point of ellipse
ellipse_center = (415,190)
# define the major and minor axes of the ellipse
axis1 = (100,50)
axis2 = (125,50)
# draw the ellipse
#Horizontal
cv2.ellipse(imageEllipse, center, axis1, 0, 0, 360, (255, 0, 0), thickness=3)
#Vertical
cv2.ellipse(imageEllipse, center, axis2, 90, 0, 360, (0, 0, 255), thickness=3)
# display the output
cv2.imshow('ellipse Image',imageEllipse)
cv2.waitKey(0)

C++

// make a copy of the original image
   Mat imageEllipse = img.clone();
   // define the center point of ellipse
   Point ellipse_center(415,190);
   // define the major and minor axes of the ellipse
   Point axis1(100, 50);
   Point axis2(125, 50);
   // Draw an ellipse using the ellipse() function
   //Horizontal
   ellipse(imageEllipse, ellipse_center, axis1, 0, 0, 360, Scalar(255, 0, 0), 3, 8, 0);
   // Vertical
   ellipse(imageEllipse, ellipse_center, axis2, 90, 0, 360, Scalar(0, 0, 255), 3, 8, 0);
   // display the output
   imshow("Ellipses on Image", imageEllipse);
   waitKey();

6. Vẽ nửa hình elip trên ảnh

Đoạn code mẫu dưới đây sẽ thực hiện các công việc sau:

– Chỉ vẽ một nửa hình elip màu xanh lam

– Thay đổi hình elip màu đỏ dọc thành hình elip màu đỏ nằm ngang, được tô một nửa

Sử dụng code vẽ hình elip ở trên nhưng có sự điều chỉnh:

– Đặt endAngle cho hình elip màu xanh lam là 180 độ

– Thay đổi hướng của hình elip màu đỏ từ 90 thành 0

– Khai báo góc bắt đầu và góc kết thúc cho hình elip màu đỏ, lần lượt là 0 và 180

– Khai báo độ dày của hình elip màu đỏ là một số âm

Python

# make a copy of the original image
halfEllipse = img.copy()
# define the center of half ellipse
ellipse_center = (415,190)
# define the axis point
axis1 = (100,50)
# draw the Incomplete/Open ellipse, just a outline
cv2.ellipse(halfEllipse, ellipse_center, axis1, 0, 180, 360, (255, 0, 0), thickness=3)
# if you want to draw a Filled ellipse, use this line of code
cv2.ellipse(halfEllipse, ellipse_center, axis1, 0, 0, 180, (0, 0, 255), thickness=-2)
# display the output
cv2.imshow('halfEllipse',halfEllipse)
cv2.waitKey(0)

C++

//make a copy of the original image
   Mat halfEllipse = image.clone();
   // define the center of half ellipse
   Point ellipse_center(415,190);
   //define the axis point
   Point axis1(100, 50);
   // draw the Half Ellipse, just the outline
   ellipse(halfEllipse, ellipse_center, axis1, 0, 180, 360, Scalar(255, 0, 0), 3, 8, 0);
   // if you want to draw a Filled ellipse, use this line of code
   ellipse(halfEllipse, ellipse_center, axis1, 0, 0, 180, Scalar(0, 0, 255), -2, 8, 0);
   // display the output
   imshow("Half-Ellipses on Image", halfEllipse);
   waitKey();

7. Viết chữ trên ảnh với các định dạng khác nhau

Mục cuối của bài viết sẽ trình bày cách chú thích hình ảnh bằng văn bản. Để thực hiện việc này, sử dụng hàm putText() trong OpenCV. Cú pháp hàm như sau:

putText(image, text, org, font, fontScale, color)

– Đối số đầu tiên là hình ảnh đầu vào.

– Đối số tiếp theo là chuỗi văn bản thực tế mà chúng ta muốn chú thích hình ảnh.

– Đối số thứ ba chỉ định vị trí bắt đầu cho góc trên cùng bên trái của chuỗi văn bản.

– Hai đối số tiếp theo chỉ định kiểu phông chữ và tỷ lệ.

OpenCV hỗ trợ một số kiểu phông chữ từ bộ sưu tập phông chữ Hershey và cả phông chữ nghiêng. Cụ thể:

  FONT_HERSHEY_SIMPLEX = 0,

  FONT_HERSHEY_PLAIN = 1,

  FONT_HERSHEY_DUPLEX = 2,

  FONT_HERSHEY_COMPLEX = 3,

  FONT_HERSHEY_TRIPLEX = 4,

  FONT_HERSHEY_COMPLEX_SMALL = 5,

  FONT_HERSHEY_SCRIPT_SIMPLEX = 6,

  FONT_HERSHEY_SCRIPT_COMPLEX = 7,

  FONT_ITALIC = 16

– Tỷ lệ phông chữ là một giá trị dấu phẩy động, được sử dụng để chia tỷ lệ kích thước cơ bản của phông chữ lên hoặc xuống. Tùy thuộc vào độ phân giải của hình ảnh mà chọn một tỷ lệ phông chữ thích hợp.

– Đối số bắt buộc cuối cùng là màu sắc, được chỉ định dưới dạng BGR.

Python

# make a copy of the original image
imageText = img.copy()
#let's write the text you want to put on the image
text = 'I am a Happy dog!'
#org: Where you want to put the text
org = (50,350)
# write the text on the input image
cv2.putText(imageText, text, org, fontFace = cv2.FONT_HERSHEY_COMPLEX, fontScale = 1.5, color = (250,225,100))))
# display the output image with text over it
cv2.imshow("Image Text",imageText)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++

// make a copy of the original image
   Mat imageText = img.clone();
   // Write text using putText() function
   putText(imageText, "I am a Happy dog!", Point(50,350), FONT_HERSHEY_COMPLEX, 1.5, Scalar(250,225,100));
   imshow("Text on Image", imageText);
   waitKey(0);

Kết luận

Chú thích hình ảnh bằng các hình dạng hình học và văn bản là một cách hiệu quả để làm cho kết quả hình ảnh trực quan hơn. Hình ảnh hầu như luôn được chú thích sau khi đã được xử lý bằng các thuật toán thị giác máy tính khác nhau (ví dụ: các khung chữ nhật được vẽ xung quanh các đối tượng được phát hiện bởi một mô hình phát hiện đối tượng). Việc chú thích hình ảnh bằng các hình dạng hình học và văn bản trở nên dễ dàng khi sử dụng các hàm có sẵn trong OpenCV.

Bài viết tiếp theo sẽ giới thiệu các không gian màu trong OpenCV.

Biên dịch: Thảo Nguyễn

Để cập nhật tin tức công nghệ mới nhất và các sản phẩm của công ty AIoT JSC, vui lòng truy cập link: http://aiots.vn hoặc linhkienaiot.com

5 1 Bỏ phiếu
Article Rating
Subscribe
Notify of
guest
0 Comments
Phản hồi nội tuyến
Xem tất cả các bình luận