Hướng dẫn dùng cv2.line python

Vẽ trong OpenCV

Trực quan hóa kết quả xử lý ảnh cũng quan trọng như cách ăn diện của bạn hàng ngày vậy. Vẽ vời đẹp, chuyên nghiệp sẽ gây ấn tượng cho người xem. Nay Minh sẽ viết một số hàm vẽ cơ bản lên ảnh dùng thư viện OpenCV. Mình sẽ cố gắng code tổng quát nhất có thể để bạn có thể copy code và sử dụng ngay vào dự án của mình mà ít phải chỉnh sửa tham số. Cụ thể mình sẽ gói [wrap] các hàm vẽ lại để nó vẽ đường nét đậm nhạt tương đối theo kích thước ảnh. Điều này cực kỳ tốt khi bạn đang làm dự án Xử Lý Ảnh, Học Máy [machine learning] để xử lý nhiều ảnh với kích thước / độ phân giải đa dạng; và ta sẽ phải visualize kết quả lên trên các ảnh này. OK, let's go, chiến thôi!

Việc đầu tiên và trên hết "xẩy" đó là lấy một ảnh mẫu làm "tài liệu tham khảo" nào. Tui đã chuẩn bị sẵn cho các ông :">. Mình thích thì mình "tha thu" lên ảnh thôi :v.

girl.jpg

Ghi chữ lên ảnh

Trong OpenCV để ghi chữ lên ảnh, bạn sẽ dùng hàm cv2.putText. Hàm này sẽ ghi chữ trực tiếp lên ảnh, do đó nó sẽ chỉnh sửa trực tiếp trên ảnh gốc. Nếu muốn giữ ma trận ảnh gốc chưa vẽ, ta cần phải sao chép [copy / clone] ra. Một số tham số cho hàm putText:

  • text: nội dung chữ.
  • org: tọa độ đặt chữ lên ảnh, nó sẽ ứng với góc dưới bên trái của "text" [bottom-left].
  • fontFace: font chữ, tham khảo thêm @ //docs.opencv.org/4.3.0/d6/d6e/group__imgproc__draw.html#ga0f9314ea6e35f99bb23f29567fc16e11. Có vẻ hiện tại OpenCV chỉ hỗ trợ font chữ Hershey nên còn nhiều hạn chế cho lựa chọn font chữ.
  • fontScale: kích thước chữ, scale to bao nhiêu lần so với kích thước font chữ chuẩn.
  • color: màu sắc chữ theo hệ màu BGR. Tham khảo hệ màu @ Tut 1.1: Xử lý ảnh - Cấu trúc dữ liệu ảnh trong OpenCV. Pixel là gì?.
  • thickness: độ dày [đậm] của chữ. Trong word ta hay gọi là bold.
  • lineType: độ "smooth" của nét.
  • bottomLeftOrigin: dùng hệ trục ở góc trái hay không? Set False tức dùng gốc tọa độ ở góc phía trên bên trái ảnh, đây là gốc tọa độ chuẩn trong Xử Lý Ảnh.

Minh đã cá nhân hóa này thành một hàm draw_text[] cho phép đặc tả size ảnh tương đối theo kích thước ảnh, nó sẽ ước lượng tính toán tự động fontScale phù hợp để chữ to bằng size % so với cạnh ngắn của ảnh. Điểm lợi của cách làm này đó là với ảnh độ phân giải cao chữ cũng sẽ "to" ra tương ứng, hoặc "nhỏ" lại một cách tương dối theo kích thước / độ phân giải ảnh. Tránh việc "tuning" giá trị fontScale, thickness khi xử lý nhiều loại ảnh khác nhau.

Set thickness bằng zero [0] vào hàm draw_text[] của mình để nó tự tính độ đậm thickness phù hợp với kích thước chữ. Tọa độ chữ mình sẽ nhận vô giá trị 0-1 tương đối so với kích thước ảnh.

Cách sử dụng được minh họa trong đoạn code bên dưới:

  • Mình ghi chữ "Hi em" @ [0.70, 0.12] màu đỏ, size chữ 5%; is_copy=True bằng True để clone ảnh kết quả, không vẽ trực tiếp lên ảnh gốc.
  • Mình tiếp tục ghi chữ "Good afternoon" lên ảnh vừa vẽ ở bước trên @ [0.55, 0.18] màu vàng, size chữ 3% [nhỏ hơn chữ trên]; lưu ý is_copy=False để ghi chữ tiếp lên ma trận ảnh vừa rồi.

draw_text.py

import cv2

IMAGE = "girl.jpg"
OUT_IMAGE = "girl_text.jpg"

def draw_text[image, 
              text, 
              x,
              y,
              color_bgr=[255, 0, 0], 
              size=0.05, # in the range of [0, 1.0]
              font_face=cv2.FONT_HERSHEY_PLAIN,
              thickness=0, # 0: auto
              line_type=cv2.LINE_AA,
              is_copy=True]:
    """
        Supported Fonts: //docs.opencv.org/4.3.0/d6/d6e/group__imgproc__draw.html#ga0f9314ea6e35f99bb23f29567fc16e11
        Line Types: //docs.opencv.org/4.3.0/d6/d6e/group__imgproc__draw.html#gaf076ef45de481ac96e0ab3dc2c29a777
    """
    assert size > 0
    
    image = image.copy[] if is_copy else image # copy/clone a new image
    if not text: # empty text
        return image
    
    # //docs.opencv.org/4.3.0/d6/d6e/group__imgproc__draw.html#ga3d2abfcb995fd2db908c8288199dba82
    [text_width, text_height], _ = cv2.getTextSize[text, font_face, 1.0, thickness] # estimate text size
    
    # calculate font scale
    h, w = image.shape[:2]
    short_edge = min[h, w]
    expect_size = short_edge * size
    font_scale = expect_size / text_height
    
    # calc thickness
    if thickness  cạnh ngắn sẽ là 480px => 1% của 480px sẽ là 4.8px => thickness = int[4.8] = 4.

draw_line.py

import cv2

IMAGE = "girl.jpg"
OUT_IMAGE = "girl_line.jpg"

def draw_line[image,
              x_from,
              y_from,
              x_to,
              y_to,
              color_bgr=[255, 0, 0], 
              size=0.01, # 1%
              line_type=cv2.LINE_AA,
              is_copy=True]:
    assert size > 0
    
    image = image.copy[] if is_copy else image # copy/clone a new image
    
    # calculate thickness
    h, w = image.shape[:2]
    short_edge = min[h, w]
    thickness = int[short_edge * size]
    thickness = 1 if thickness  0
    
    image = image.copy[] if is_copy else image # copy/clone a new image
    
    # calculate thickness
    h, w = image.shape[:2]
    short_edge = min[h, w]
    thickness = int[short_edge * size]
    thickness = 1 if thickness  0:        
        short_edge = min[h, w]
        thickness = int[short_edge * size]
        thickness = 1 if thickness  0:        
        short_edge = min[h, w]
        thickness = int[short_edge * size]
        thickness = 1 if thickness  0
    
    image = image.copy[] if is_copy else image # copy/clone a new image
    
    # calculate thickness
    h, w = image.shape[:2]
    if size > 0:        
        short_edge = min[h, w]
        thickness = int[short_edge * size]
        thickness = 1 if thickness 

Chủ Đề