import numpy as np
def non_max_suppression_fast(boxes, labels, overlapThresh):
# if there are no boxes, return an empty list
if len(boxes) == 0:
return []
# if the bounding boxes integers, convert them to floats --
# this is important since we'll be doing a bunch of divisions
if boxes.dtype.kind == "i":
boxes = boxes.astype("float")
#
# initialize the list of picked indexes
pick = []
# grab the coordinates of the bounding boxes
x1 = boxes[:,0]
y1 = boxes[:,1]
x2 = boxes[:,2]
y2 = boxes[:,3]
# compute the area of the bounding boxes and sort the bounding
# boxes by the bottom-right y-coordinate of the bounding box
area = (x2 - x1 + 1) * (y2 - y1 + 1)
idxs = np.argsort(y2)
# keep looping while some indexes still remain in the indexes
# list
while len(idxs) > 0:
# grab the last index in the indexes list and add the
# index value to the list of picked indexes
last = len(idxs) - 1
i = idxs[last]
pick.append(i)
# find the largest (x, y) coordinates for the start of
# the bounding box and the smallest (x, y) coordinates
# for the end of the bounding box
xx1 = np.maximum(x1[i], x1[idxs[:last]])
yy1 = np.maximum(y1[i], y1[idxs[:last]])
xx2 = np.minimum(x2[i], x2[idxs[:last]])
yy2 = np.minimum(y2[i], y2[idxs[:last]])
# compute the width and height of the bounding box
w = np.maximum(0, xx2 - xx1 + 1)
h = np.maximum(0, yy2 - yy1 + 1)
# compute the ratio of overlap
overlap = (w * h) / area[idxs[:last]]
# delete all indexes from the index list that have
idxs = np.delete(idxs, np.concatenate(([last],
np.where(overlap > overlapThresh)[0])))
# return only the bounding boxes that were picked using the
# integer data type
final_labels = [labels[idx] for idx in pick]
final_boxes = boxes[pick].astype("int")
return final_boxes, final_labels
boxes và Chúng ta sẽ thu được kết quả như sau:
final_boxes
>>>
array([[ 16, 647, 83, 711],
[894, 636, 956, 701],
[ 11, 87, 79, 149],
[892, 80, 953, 139]])
final_labels
>>>
['bottom_left', 'bottom_right', 'top_left', 'top_right']
Perspective Transform
Trước tiên chúng ta cần xác định được tọa độ các điểm nguồn dựa vào vị trí của các bxoes đã detect được. Chúng ta đơn giản hóa quá trình này bằng cách lấy điểm chính giữa của từng box thành điểm nguồn. Sử dụng hàm sau
def get_center_point(box):
xmin, ymin, xmax, ymax = box
return (xmin + xmax) // 2, (ymin + ymax) // 2
final_points
từ tập hợp các boxes thu được phía trên
final_points = list(map(get_center_point, final_boxes))
Transform sang tọa độ đích
Ở đây fix cứng tọa độ đích là ảnh 500x300 cho gần với kích thước của chứng minh thư. Bạn đọc có thể thay đổi nó. Tiếp theo chúng ta tiến hành transform
source_points = np.float32([
label_boxes['top_left'], label_boxes['top_right'], label_boxes['bottom_right'], label_boxes['bottom_left']
])
# Transform
crop = perspective_transoform(image, source_points)
Kết luận
Bài này khá đơn giản với mong muốn các bạn có thể hiểu đại khái các bước xử lý Alignment cho ảnh chứng minh thư như thế nào. Bằng việc sử dụng thư viện Detecto giúp cho việc training mô hình rất đơn giản và dần dần khiến chúng ta có cảm giác việc sử dụng Deep Learning cũng là một công cụ giúp chúng ta lập trình và giải quyết bài toán tốt hơn chứ không phải một cái gì đó khủng khiếp như người ta từng nghĩ cả. Chúc các bạn vui vẻ và hẹn gặp lại trong những bài viết sau
» Tin mới nhất:
» Các tin khác: