Skip to content
Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Close

Search

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Close

Search

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Computer Vision

Chi tiết cách đo kích thước vật thể bằng OpenCV thuần

By Chủ tiệm Mì
July 21, 2020 6 Min Read
10

Chào tuần mới anh Mì AI, hôm nay chúng ta sẽ sử dụng OpenCV thuần với Python để thử đo kích thước các vật thể trong ảnh nhé.

Việc đo kích thước này mình cũng nói trước luôn mấy điểm:

  • Thứ nhất, việc đo chỉ mang tính chất tham khảo, không thể nào chính xác 100% như mang thước ra đo hoặc dùng các máy đo chuyên dụng
  • Thứ hai, do ở đây mình sử dụng một ảnh bất kì làm sample, không cân chỉnh camera một cách bài bản nên có thể kích thước sẽ ảnh hưởng bởi góc nghiêng của camera.

Tuy nhiên, với mục đích học tập thì hoàn toàn chấp nhận được. Ngoài ra mình cũng đã có 1 bài đo khoảng cách tương tự các bạn cũng có thể đọc để tham khảo nhé: tại đây.

Okie con dê! Bắt đầu tìm hiểu nào!

Phần 1 – Làm sao để đo kích thước vật thể trong ảnh?

Rõ ràng với logic thông thường thì muốn đo kích thước vật thể trong ảnh ta phải biết được các yếu tố như: Khoảng cách từ camera đến vật khi chụp, Tiêu cự của camera, góc chụp…..rất phức tạp như hình dưới:

Nguồn: Tại đây

Tuy nhiên với anh em Mì ngại học toán thì mình sẽ có một cách đơn giản hơn như sau: (bạn nào thích làm phức tạp có thể nghiên cứu cách căn chỉnh camera tại đây).

  • Đầu tiên ta chọn một vật nào đó ta biết kích thước gọi là “Vật tham chiếu“. Ta nên chọn một viên bi tròn hay vật gì đó hình tròn để dễ dàng hơn trong việc tính toán. Giả sử viên bi có đường kính thật $Dr = 2cm = 20mm$
  • Tiếp theo ta đặt Vật tham chiếu đó vào ảnh cùng với các Vật muốn đo kích thước và chụp một tấm.
  • Sau đó, Giả sử ta đo được đường kính trong ảnh của Vật tham chiếu là $Dc = 100 pixel$, ta suy ra kích thước thật của 1 pixel là 20/100 = 0.2mm (goi là số $P$)
  • Bước cuối cung, ta đo kích thước trong ảnh Vật muốn đo bằng pixel, sau đó nhân với $P$ là sẽ ra kích thước thật của vật.

Các bạn đã nắm được tinh thần rồi chứ? Nếu còn vướng mắc thì các bạn cứ post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup để thảo luận nhé.

Phần 2 – Triển khai bài toán

Việc đầu tiên là ta phải tìm cách đo được kích thước bằng pixel của các vật trong ảnh, đó là yếu tố tiên quyết cho bài toán này.

Giả sử ta có một tấm ảnh như sau và ở đây Vật tham chiếu là đồng xu 1 Rufiuaa của Maldives (kỷ niệm chuyến đi năm ngoái của mình kaka) và Vật cần đo là chiếc USB bên cạnh.

đo kích thước vật thể

Ta đã biết đồng xu này có kích thước thật là 2cm = 20mm. Bây giơ chúng ta sẽ cùng nhau thực hiện các bước nhé.

Tiền xử lý và tìm cạnh

Việc đầu tiên là phải thực hiện chuyển về ảnh xám và tìm cạnh để bước sau tìm contour:

    # Đọc file ảnh
    image = cv2.imread(filename)
    # Chuyển thành ảnh xám
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # Làm mờ ảnh
    gray = cv2.GaussianBlur(gray, (blur_kernel, blur_kernel), 0)

    # Áp dụng Canny tìm cạnh
    edged = cv2.Canny(gray, canny_low, canny_high)
    edged = cv2.dilate(edged, (d_e_kernel, d_e_kernel), iterations=1)
    edged = cv2.erode(edged, (d_e_kernel, d_e_kernel), iterations=1)

Sau bước này ta sẽ có được bức ảnh như sau:

đo kích thước vật thể

Nhìn qua ta đã thấy có thể tìm được các contour của đồng xu và cái USB rồi. Chú ý là ở đây do nền của mình khá phức tạp nên việc tìm contour khá khó,các bạn có thể thử với nền đơn giản hơn (đơn sắc, phẳng….) cho dễ nhé.

Tìm contour và xác định kích thước bằng pixel

Rồi, bay giờ ta sẽ tìm các contour trong hình, và loại bỏ các contour nhỏ để giữ lại 2 contour chính là đồng xu và USB.

    # Tìm các Contour trong ảnh
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)

    # Sắp xếp các contour từ trái qua phải
    (cnts, _) = contours.sort_contours(cnts)
    P = None

    # Duyệt các contour
    for c in cnts:
        # Nếu contour quá nhỏ -> bỏ qua
        if cv2.contourArea(c) < area_threshold:
            continue

Với các contour tìm được, chúng ta sẽ thực hiện tính toán kích thước của nó trong bằng, tính bằng Pixel. Ở đây chúng ta sử dụng một khái niệm MinAreaRect chứ ko phải Bounding Box nhé.

Các bạn có thể phân biệt theo hình sau (đỏ là MinAreaRect và xanh là bounding box):

đo kích thước vật thể
Nguồn: Tại đây
    # Lấy minRect
    box = cv2.minAreaRect(c)
    # Lấy tọa độ các đỉnh của MinRect
    box = cv2.boxPoints(box)
    box = np.array(box, dtype="int")

    # Sắp xếp các điểm theo trình tự
    box = perspective.order_points(box)

    # Vẽ contour
    cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)

    # Tinh toán 4 trung diểm của các cạnh
    (tl, tr, br, bl) = box
    (tltrX, tltrY) = midpoint(tl, tr)
    (blbrX, blbrY) = midpoint(bl, br)
    (tlblX, tlblY) = midpoint(tl, bl)
    (trbrX, trbrY) = midpoint(tr, br)

    # Tính độ dài 2 chiều
    dc_W = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
    dc_H = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

Sau bước này ta đã có được kích thước Vật tham chiếu (đồng xu) bằng Pixel, ta sẽ tình toán số $P$ (xem lại phần 1 nếu không nhớ $P$là gì)

$$P = Real size / Size in pixel$$

Vậy ta tính tiếp nào:

P = ref_width / dc_H

Và kích thước thật của các Vật cần đo (USB) là:

dr_W = dc_W * P
dr_H = dc_H * P

Sau khi đã tính toán xong thì chúng ta chỉ cần vẽ lên ảnh cho đẹp, kẻ các khung contour là okie.

Full code của hàm này là:

def find_object_in_pix(orig, edge, area_threshold=3000):
    # Tìm các Contour trong ảnh
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)

    # Sắp xếp các contour từ trái qua phải
    (cnts, _) = contours.sort_contours(cnts)
    P = None

    # Duyệt các contour
    for c in cnts:
        # Nếu contour quá nhỏ -> bỏ qua
        if cv2.contourArea(c) < area_threshold:
            continue
            
        # Tính toán 2 chiều bằng Pixel
        dc_W, dc_H, tltrX, tltrY, trbrX, trbrY = get_distance_in_pixels(orig, c)

        # Nếu là đồng xu
        if P is None:
            # Cập nhật số P
            P = ref_width / dc_H
            # Gán luôn kích thước thật bằng số đã biết
            dr_W = ref_width
            dr_H = ref_width
        else: # Nếu là các vật khác
            # Tính toán kích thước thật dựa vào kích thước pixel và số P
            dr_W = dc_W * P
            dr_H = dc_H * P

        # Ve kich thuoc len hinh
        cv2.putText(orig, "{:.1f} mm".format(dr_H), (int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX, 1,
                    (0, 0, 255), 2)
        cv2.putText(orig, "{:.1f} mm".format(dr_W), (int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX, 1,
                    (0, 0, 255), 2)

    return orig

Và bước cuối cùng là show ảnh đã vẽ vời các kiểu lên màn hình:

đo kích thước vật thể

Mình có chia sẻ github có code sẵn để các bạn tải về chạy thử nhé: tại đây . Chú ý cài thư viện bằng lệnh:

pip install -r setup.txt

Done rồi,! Vậy là mình dã guide các bạn dùng OpenCV để đo kích thước các vật thể trong camera được rồi. Các bạn có thể phát triển, ứng dụng cho các bài toán riêng của các bạn nhé.

Chúc các bạn thành công!

Hãy join cùng cộng đồng Mì AI nhé!

Fanpage: http://facebook.com/miaiblog
Group trao đổi, chia sẻ: https://www.facebook.com/groups/miaigroup
Website: https://miai.vn/
Youtube: http://bit.ly/miaiyoutube

Cảm ơn bài tham khảo cực hay của tác giả Adrian Rosebrock!

Tags:

cannycontoursđo kích thước vật thểđo kích thướng vậtedgeobject dimensionobject dimension measureopencv
Author

Chủ tiệm Mì

Follow Me
Other Articles
Previous

Chi tiết các cài đặt và thiết lập môi trường ảo trong lập trình Python

Next

[DA-DS] Triển khai mô hình dự báo đơn giản (Chương 1/2)

10 Comments
  1. Minh says:
    December 22, 2020 at 6:54 am

    Chào anh,
    Mình có cần calib lại tấm ảnh trước không anh ?

    Reply
    1. Nguyễn Chiến Thắng says:
      December 22, 2020 at 7:42 am

      Không cần em. Nếu có thì tốt hơn.

      Reply
  2. Minh says:
    August 6, 2021 at 12:21 pm

    lấy khoảng cách giữa hai vật thể trên ảnh thì sao anh

    Reply
    1. Nguyễn Chiến Thắng says:
      August 10, 2021 at 4:14 pm

      Cũng thế em. Phải có 1 vật làm mốc! Coi khoảng cách giữa 2 vật thể là kích thước của cái đường thằng kia. Quan trọng là tính toán để lấy được toạ độ đường thẳng đó. Em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup nhé!

      Reply
      1. Minh Tú says:
        March 27, 2022 at 4:06 pm

        Em chào anh,
        Nếu vật cần đo kích thước đặt trên vật tham chiếu là tờ A4 thì xử lý như nào được ạ ?

        Reply
        1. Nguyễn Chiến Thắng says:
          March 27, 2022 at 4:23 pm

          À thì em dùng kích thước tờ giấy A4 làm tham chiếu. Vậy thì cừ làm sao ta detect dược tờ giấy A4 trong hình là ta tính toán được. Chi tiết em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup cho tiện trao đổi nhé!

          Reply
  3. Minh Hoàng says:
    October 30, 2022 at 11:59 pm

    anh ơi em có một yêu cầu khó hơn về bài toán này đó là đo kích thước ảnh mà không sử dụng đến vật tham chiếu thì phải làm thế nào ạ?

    Reply
    1. Nguyễn Chiến Thắng says:
      November 4, 2022 at 2:22 pm

      Bạn post lên https://facebook.com/groups/miaigroup trao đổi cho tiện nhé!

      Reply
  4. Hoàng says:
    August 23, 2023 at 9:30 pm

    anh co video huong dan khong ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      August 26, 2023 at 5:13 pm

      Bài này anh lại không có. Em có thể hỏi trên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup thêm nhé!

      Reply
Show Comments

Leave a Reply Cancel reply

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

Recent Posts

  • Tìm hiểu và cài đặt OpenClaw – trợ lý ảo 24/7 thông minh đa chức năng – Mì Ai
  • Dùng thử Pika – robot học Tiếng Anh cho trẻ cực đỉnh – Mì AI
  • TopView.AI 4.0 – nền tảng tạo AI video cộng tác bá đạo – Mì AI
  • Storm MCP – giải pháp nhanh gọn nhẹ để có MCP Server trong 5 phút – Mì AI
  • VoxCPM thử voice cloning với checkpoint finetune Tiếng Việt – Mì AI

Recent Comments

  1. Chủ tiệm Mì on Thử xây dựng hệ thống Agentic AI với LangGraph – Mì AI
  2. Nguyễn Chiến Thắng on [Nhận diện biển số xe] Chương 3 – Phát hiện biển số bằng OpenCV thuần
  3. Trần Sơn Dương on [Nhận diện biển số xe] Chương 3 – Phát hiện biển số bằng OpenCV thuần
  4. Salomon on [CV] Thử làm model cảnh báo ngủ gật cho tài xế oto bằng Dlib và Resnet
  5. khang on Xây dựng hệ thống nhận diện thủ ngữ – ngôn ngữ ký hiệu tay – để giao tiếp với người khuyết tật

Categories

  • Basic
  • Computer Vision
  • Data Science – Data Analysis
  • Generative AI
  • MÌ ÚP
  • Natural Language Processing
  • RNN-LSTM-GRU
  • Share Data

Là người đi trước, hãy biết đưa tay lại phía sau.

Nguyễn Chiến Thắng
Cảm ơn các bạn đã ủng hộ Mì AI!