Computer Vision

Advanced contour properties

Xin chào, ở bài viết trước chúng ta đã tìm hiểu về các thuộc tính cơ bản của Contour như trọng tâm, chu vi, diện tích, bounding box. Ở bài này chúng ta sẽ tìm hiểu sâu hơn về các thuộc tính khác như Aspect Ratio, Extent, Convex hull, Solidity.

Hiểu biết rõ về các thuộc tính của Contour có thể giúp chúng ta tránh khỏi cái bẫy Over-Engineering, nói cách khác là tránh “Giết gà bằng dao mổ trâu”.


ASPECT RATIO

Aspect Ratio chính là tỉ lệ giữa chiều rộng (Width) và chiều cao (Height) của shape. Dù đơn giản nhưng Aspect Ratio lại rất mạnh mẽ. Chúng ta có thể sử dụng Aspect Ratio để phân biệt giữa hình vuông và hình chữ nhật, để xác định chữ viết tay trong bức ảnh.

Nếu Aspect Ratio < 1: Contour có chiều cao lớn hơn chiều rộng.

Nếu Aspect Ratio > 1: Contour có chiều rộng lớn hơn chiều cao.

Nếu Aspert Ratio = 1: Contour có chiều rộng bằng (hoặc xấp xỉ) với chiều cao.


EXTENT

Extent chính là tỉ lệ giữa diện tích của Contour và diện tích của Bounding Box của Contour đó. Giá trị của Extent luôn nhỏ hơn hoặc bằng 1.

Chúng ta sẽ sử dụng Extent để phân biệt các shapes có trong bức ảnh.


CONVEX HULL

Convex Hull là một đa giác với kích thước nhỏ nhất có thể chứa tất cả các điểm của Contour. OpenCV cung cấp function cv2.convexHull() để giúp chúng ta tìm ra Convex Hull của một Contour.

scipy-spatial-ConvexHull-1

Figure 1 – Convex Hull

Chúng ta sẽ sử dụng Convex Hull trong “Nhận dạng cử chỉ bàn tay” (Hand gesture recognition)

contours_convexity_defects

Figure 2 – Convex Hull and Hand gesture recognition


SOLIDITY

Solidity chính là tỉ lệ giữa diện tích của Contour và diện tích của Convex Hull của Contour đó. Giá trị của Solidity luôn nhỏ hơn hoặc bằng 1.

Tương tự với Extent, chúng ta sẽ sử dụng Solidity để phân biệt các shapes có trong bức ảnh.


THỰC HÀNH

Chúng ta đã tìm hiểu sơ qua các thuộc tính mới của Contour, để hiểu rõ hơn về các khái niệm này cũng như cách áp dụng trong thực tế chúng ta sẽ thực hiện một số ví dụ đơn giản.

Việc sử dụng Contour một cách thông minh có thể giúp chúng ta giải quyết các bài toán tưởng chừng phức tạp nhưng thực sự lại rất đơn giản.

Hãy nhớ rằng: Luôn luôn xem xét đến Contour trước khi áp dụng các phương pháp Computer Vision phức tạp hơn.

NHẬN DIỆN X VÀ O TRONG BÀN CỜ CARO

Input:

tictactoe

Figure 1 – Tic-tac-toe

Example code:

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"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)[1]

cnts = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for (i, c) in enumerate(cnts):
	area = cv2.contourArea(c)
	(x,y,w,h) = cv2.boundingRect(c)

	hull = cv2.convexHull(c)
	hullArea = cv2.contourArea(hull)

	solidity = 0

	if hullArea != 0:
		solidity = area / hullArea

	char = "?"

	if solidity > 0.95:
		char = "O"
	elif solidity > 0.25:
		char = "X"

	if char != "?":
		cv2.drawContours(image, [c], -1, (0,255,0), 2)
		cv2.putText(image, char, (x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (0,0,255), 2)

	print("{} (Contour #{}) -- solidity={:.2f}".format(char, i + 1, solidity))

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

Output:

tictactoe

Giải thích:

Để phân biệt giữa X và O chúng ta sử dụng Solidity. Để tính được giá trị Solidity chúng ta cần diện tích của Contour và diện tích của Convex Hull (sử dụng function cv2.contourArea()).

Dựa vào đặc điểm của X và O trong bàn cờ caro ta thấy rằng, diện tích của O sẽ tương đương với Convex Hull của nó, còn đối với X, diện tích của Contour sẽ rất nhỏ so với Convex Hull. Do đó, nếu Solidity > 0.95 thì đó chắc chắn là O, ngược lại nếu 0.25 < Solidity <= 0.95 thì đó là X.

Kết quả nhận được khá ấn tượng đúng không nào.

NHẬN DIỆN CÁC HÌNH CƠ BẢN

Input:

shapes

Figure 2 – Basic shapes

Example code:

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"])
hullImage = np.zeros(image.shape[:2], dtype="uint8")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

gray = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)[1]

cnts = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]

for (i, c) in enumerate(cnts):
	area = cv2.contourArea(c)
	(x,y,w,h) = cv2.boundingRect(c)

	aspectRatio = w / float(h)
	extent = area / float(w*h)
	hull = cv2.convexHull(c)
	hullArea = cv2.contourArea(hull)

	solidity = 0

	if hullArea != 0:
		solidity = area / float(hullArea)

	cv2.drawContours(hullImage, [hull], -1, 255, 2)
	cv2.drawContours(image, [c], -1, (0,255,0), 2)

	print("(Contour #{}) -- ratio={:.2f} -- solidity={:.2f} -- extent={:.2f}".format(i + 1, aspectRatio, solidity, extent))

	shape = "?"
	if solidity >= 0.95:
		if extent >= 0.95:
			if aspectRatio >= 0.95:
				shape = "Square"
			else:
				shape = "Rectangle"
		elif extent >= 0.7:
			if aspectRatio >= 0.9:
				shape = "Circle"
			else:
				shape = "Ellipse"
		else:
			if aspectRatio >= 0.9:
				shape = "Triangle"
			else:
				shape = "Diamond"
	elif solidity >= 0.9:
		shape = "Heart"
	else:
		shape = "Star"

	cv2.putText(image, shape, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (255, 0, 0), 1)

cv2.imshow("Output", image)
cv2.imshow("Hull", hullImage)
cv2.waitKey(0)

Output:
basicshapes

Trong ví dụ trên chúng ta đã áp dụng Aspect Ratio, Extent, Convex Hull và Solidity để phân loại các hình ảnh.


SUMMARY

Chỉ với các thuộc tính của Contour, chúng ta đã có thể nhận diện được các hình cơ bản cũng như phân biệt được X và O trên bàn cờ Caro. Hãy thưởng thức và sáng tạo thêm nhé!. Cảm ơn các bạn đã theo dõi bài viết.

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

One thought on “Advanced contour properties

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