Computer Vision

Contours

A contour is a curve of points, with no gaps in the curve. Contours are extremely useful for such things as shape approximation and analysis.

Để tìm contour, đầu tiên chúng ta cần nhị phân hóa bức ảnh bằng cách sử dụng các phương pháp edge detection hoặc thresholding.

COUNTING BALLOONS

Functions:

  • Xác định contours trong bức ảnh:

OpenCV 2.4 – contours, hierarchy = cv2.findContours(binaryImage, typeofContour, cv2.CHAIN_APPROX_SIMPLE)

OpenCV 3.x – modifiedImage, contours, hierarchy = cv2.findContours(binaryImage, typeofContour, cv2.CHAIN_APPROX_SIMPLE)

Trong đó:
+ contours – một List chứa các contours có trong image. Mỗi contour được biểu diễn ở dạng ma trận 3-D với kích thước (N, 1, 2), trong đó: N là số lượng điểm có trong mỗi contour.
+ hierarchy – một ma trận (1, N, 4) chứa mối quan hệ cấu trúc giữa các contours.
+ modifiedImage – the image itself after applying the contour detection algorithm.
+ binaryImage – image đã được áp dụng Threshold hoặc Egde Detector; Chú ý: binaryImage sẽ bị sửa đổi trong quá trình áp dụng findContours.
+ typeofContour cv2.RETR_EXTERNAL, cv2.RETR_LIST, cv2.RETR_COMPcv2.RETR_TREE.

  • Vẽ đường viền theo contours:

cv2.drawContours(image, contours, contourIndex, (B, G, R), thickness)

Trong đó:
+ image – hình ảnh cần vẽ contours.
+ contours – một List chứa các contours có trong image.
+ contourIndex – index của contour cần vẽ; -1 nếu muốn vẽ tất cả contours.
+ (B, G, R) – màu sắc của đường contour.
+ thickness – kích thước đường contour.

  • Tìm tọa độ và kích thước của “Enclosing box” bao quanh contour:

x, y, w, h = cv2.boundingRect(contours)

  • Tìm tọa độ tâm và kích thước của “Enclosing circle” nhỏ nhất bao quanh contour:

(centerX, centerY), radius = cv2.minEnclosingCircle(contours)

Trong đó:
+ (centerX, centerY) – tâm của đường tròn bao quanh contour, bắt buộc phải là tuple.
+ radius – bán kính của đường tròn.

Example 1: Counting balloons

import numpy as np
import argparse
import cv2

def auto_canny(image, sigma = 0.33):
    v = np.median(image)
    lower = int(max(0, (1.0-sigma)*v))
    upper = int(min(255, (1.0+sigma)*v))
    edged = cv2.Canny(image, lower, upper)

    return edged

# take image
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image")
args = vars(ap.parse_args())

# preprocessing
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.medianBlur(gray, 7)
cv2.imshow("image", image)

edged = auto_canny(blurred)
cv2.imshow("Edges", edged)

# contour detection
contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print("I found {} balloons in this image".format(len(contours)))

# draw contours
balloons = image.copy()
cv2.drawContours(balloons, contours, -1, (0, 255, 0), 2)
cv2.imshow("Coins", balloons)
cv2.waitKey(0)

# extract balloon from image
for (i, c) in enumerate(contours):
    (x,y,w,h) = cv2.boundingRect(c)
    print("Balloon #{}".format(i+1))
    balloon= image[y:y+h, x:x+w]
    cv2.imshow("Balloon", balloon)
    # masking
    mask = np.zeros(image.shape[:2], dtype="uint8")
    (centerX, centerY), radius = cv2.minEnclosingCircle(c)
    cv2.circle(mask, (int(centerX), int(centerY)), int(radius), 255, -1)
    mask = mask[y:y+h, x:x+w]
    cv2.imshow("Masked balloon", cv2.bitwise_and(balloon, balloon, mask=mask))
    # terminate program
    if (cv2.waitKey(0) & 0xFF) == 27:
        break

cv2.destroyAllWindows()

Output:
Balloons

Figure 1 – Balloons

edgecontour

Figure 2 – Edges and contours

Trong example 1, trước khi sử dụng Canny Edge Detector, chúng ta đã áp dụng median blurring (có thể sử dụng Gaussian blurring) để giảm nhiễu. Để đơn giản chúng ta sử dụng Automatic Canny Edge Detector.

Kết quả nhận được sau khi áp dụng auto_canny() sẽ được đưa vào funtion cv2.findContours() và ta sẽ nhận được tập hợp các contours có trong bức ảnh.

Để vẽ các đường contour, chúng ta sử dụng function cv2.drawContour(), với đường contour màu xanh, thickness = 2.

Tiếp theo chúng ta tiến hành tách từng balloon. Function cv2.boundingRect() sẽ trả về tọa độ và kích thước của hình chữ nhật bao quanh từng contour, còn function cv2.minEnclosingCircle() trả về tâm và bán kính của đường tròn nhỏ nhất bao quanh contour. Sau đó áp dụng masking, ta có thể lọc ra từng balloon như sau:

balloon

Figure 3 – Balloon

Nhấn Esc để thoát khỏi chương trình.

Qua ví dụ trên ta thấy rằng, Contour là một công cụ mạnh mẽ, cho phép chúng ta đếm và chiết xuất các đối tượng trong bức ảnh. Nhưng mọi thứ chỉ mới bắt đầu, hãy cứ tiếp tục vọc vạch nhé, còn những điều rất thú vị đang ở phía trước.

Cảm ơn các bạn đã theo dõi bài viết.

Thân ái và quyết thắng.

Reference:
[1] Automatic Canny Edge Detector
[2] Contours in OpenCV.

One thought on “Contours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s