Computer Vision

Simple contour properties

Xin chào, trong bài viết này chúng ta sẽ tìm hiểu về một số thuộc tính của Contour, bao gồm:

  1. Trọng tâm của Contours;
  2. Diện tích của Contours;
  3. Chu vi của Contours,
  4. Bounding Boxes;
  5. Rotated Bounding Boxes;
  6. Minimum Enclosing Circles;
  7. Fitting an Ellipse.

TRỌNG TÂM CỦA CONTOURS

Trọng tâm của Contour đơn giản là trung bình cộng của tất cả các tọa độ có trong Contour. Để đơn giản hóa việc tìm trọng tâm, OpenCV cung cấp function cv2.moments().

M= cv2.moments(contour)

centroidX = M[“m10”] / M[“m00”]

centroidY = M[“m01”] / M[“m00”]

Example 1 – Centroid of contours

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	M = cv2.moments(c)
	centroidX = int(M["m10"] / M["m00"])
	centroidY = int(M["m01"] / M["m00"])
	cv2.circle(image, (centroidX, centroidY), 5, (0,255,0), -1)
	cv2.drawContours(image, [c], -1, (0,255,0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

Output:
centroid


DIỆN TÍCH VÀ CHU VI CỦA CONTOUR

Để tính diện tích và chu vi của Contours, OpenCV cung cấp function cv2.contourArea() và cv2.arcLength()

Function:

dientich = cv2.contourArea(contour)

chuvi = cv2.arcLength(contour, closed)

Trong đó:

  • contour – contour cần tính chu vi, diện tích;
  • closed – nếu closed=True thì sẽ nhận được chu vi đóng.

Example 2 – Diện tích và chu vi của contours

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	M = cv2.moments(c)
	centroidX = int(M["m10"] / M["m00"])
	centroidY = int(M["m01"] / M["m00"])
	cv2.circle(image, (centroidX, centroidY), 5, (0,255,0), -1)
	cv2.drawContours(image, [c], -1, (0,255,0), 2)
	s = cv2.contourArea(c)
	c = cv2.arcLength(c, True)
	cv2.putText(image, "S={:.2f}".format(s), (centroidX-50, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,0), 1)
	cv2.putText(image, "D={:.2f}".format(c), (centroidX-50, image.shape[0]-30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,0), 1)

cv2.imshow("Image", image)
cv2.waitKey(0)

Output:
area


BOUNGDING BOX VÀ ROTATED BOUNDING BOX

Bounding Box và Rotated Bounding Box là các hình chữ nhật bao quanh Contour. Để vẽ Bounding Box và Rotated Bounding Box, OpenCV cung cấp function cv2.boundingRect() và cv2.minAreaRect().

Function:

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

Trong đó:

  • x, y – tọa độ đỉnh top-left của bounding box;
  • w, h – width và height của bounding box;
  • contour – contour cần tìm bounding box.

box = cv2.minAreaRect(contour)

newcontour = cv2.boxPoints(box)

Trong đó:

    • box – một tuple chứa tọa độ trọng tâm, kích thước và góc quay của rotated bounding box, box = ((cx, cy), (w, h), angle). Chú ý: angle là góc quay để bounding box có thể bao quanh đối tượng với diện tích nhỏ nhất, có giá trị trong khoảng [-90, 0), với góc quay dương là theo chiều kim đồng hồ (có nghĩa là bounding luôn quay ngược chiều kim đồng hồ). Góc angle KHÔNG phải góc quay của đối tượng theo bất kỳ trục nào;
  • newcontour – vì rotated bounding box không thể được vẽ bởi function cv2.rectangle() nên chúng ta cần một contour mới, do đó rotated bounding box sẽ được vẽ bởi function cv2.drawContours().

Example 3 – Bounding Box

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	x,y,w,h = cv2.boundingRect(c)
	cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

Output:
bounding

Example 4 – Rotated Bounding Box

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	box = cv2.minAreaRect(c)
	box = np.int0(cv2.boxPoints(box))
	cv2.drawContours(image, [box], -1, (0,255,0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

Output:
rotatedBounding


MINIMUM ENCLOSING CIRCLES

Minimum Enclosing Circle là vòng tròn có kích thước nhỏ nhất có thể bao quanh Contour. Để vẽ Minimum Enclosing Circle, OpenCV cung cấp function cv2.minEnclosingCircle().

Function:

(x, y), R = cv2.minEnclosingCircle(contour)

Trong đó:

  • (x, y) – tọa độ tâm đường tròn bao quanh contour;
  • R – bán kính đường tròn.

Example 5 – Minimum Enclosing Circles

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	(x,y), r = cv2.minEnclosingCircle(c)
	cv2.circle(image, (int(x), int(y)), int(r), (0,255,0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

Output:
mincircle


FITTING AN ELLIPSE

OpenCV cung cấp function cv2.fitEllipse() để vẽ một hình ellipse có thể bao quanh contour với kích thước nhỏ nhất.
Chú ý: Để sử dụng function cv2.fitEllipse(), contour cần có ít nhất 5 điểm.
Example 6 – Fitting an Ellipse

import cv2
import numpy as np
import argparse

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

image = cv2.imread(args["image"])

bin = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
bin = cv2.threshold(bin, 230, 255, cv2.THRESH_BINARY_INV)[1]
cnts = cv2.findContours(bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for c in cnts:
	if len(c) >= 5:
		ellipse = cv2.fitEllipse(c)
		cv2.ellipse(image, ellipse, (0,255,0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

SUMMARY

Như vậy chúng ta đã tìm hiểu qua một số thuộc tính của Contours, cảm ơn các bạn đã theo dõi bài viết.

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

Reference:
[1] Structural Analysis and Shape Descriptors
[2] cv::RotatedRect Class Reference

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