Cách tạo Trình quét tài liệu bằng Python
Bạn có thể muốn số hóa một tài liệu để tiết kiệm không gian vật lý hoặc tạo một bản lưu dự phòng. Dù bằng cách nào, việc viết một chương trình có thể chuyển đổi ảnh của các tệp giấy của bạn sang định dạng chuẩn là một nhiệm vụ mà Python vượt trội.
Sử dụng kết hợp các thư viện phù hợp, bạn có thể xây dựng một ứng dụng nhỏ để số hóa tài liệu. Chương trình của bạn sẽ lấy hình ảnh của một tài liệu vật lý làm đầu vào, áp dụng một số kỹ thuật xử lý hình ảnh cho nó và xuất ra một phiên bản được quét của đầu vào.
Mục Lục
Chuẩn bị môi trường của bạn
Để theo dõi bài viết này, bạn nên làm quen với những kiến thức cơ bản về Python. Bạn cũng cần hiểu về cách làm việc với thư viện NumPy Python.
Mở bất kỳ IDE Python nào và tạo hai tệp Python. Đặt tên cho một main.py và biến đổi khác.py. Sau đó chạy lệnh sau trên thiết bị đầu cuối để cài đặt các thư viện cần thiết.
pip install OpenCV-Python imutils scikit-image NumPy
Bạn sẽ sử dụng OpenCV-Python để lấy hình ảnh đầu vào và thực hiện một số xử lý hình ảnh. Imutils để thay đổi kích thước hình ảnh đầu vào và đầu ra. scikit-image để áp dụng ngưỡng trên hình ảnh. NumPy sẽ giúp bạn làm việc với mảng.
Đợi quá trình cài đặt hoàn tất và để IDE cập nhật bộ khung của dự án. Sau khi cập nhật bộ xương hoàn tất, bạn đã sẵn sàng để bắt đầu viết mã. Mã nguồn đầy đủ có sẵn trong kho lưu trữ GitHub.
Nhập thư viện đã cài đặt
Mở tệp main.py và nhập các thư viện bạn đã cài đặt trên môi trường. Điều này sẽ cho phép bạn gọi và sử dụng các chức năng của chúng khi cần thiết.
import cv2
import imutils
from skimage.filters import threshold_local
from transform import perspective_transform
Bỏ qua lỗi xảy ra trên Perspective_transform. Nó sẽ biến mất khi bạn hoàn thành thao tác trên tệp Transform.py.
Lấy và thay đổi kích thước đầu vào
Chụp ảnh rõ nét tài liệu bạn muốn quét. Đảm bảo có thể nhìn thấy bốn góc của tài liệu và nội dung của nó. Sao chép hình ảnh vào cùng thư mục mà bạn đang lưu trữ các tệp chương trình.
Chuyển đường dẫn hình ảnh đầu vào tới OpenCV. Tạo một bản sao của ảnh gốc vì bạn sẽ cần nó trong quá trình chuyển đổi phối cảnh. Chia chiều cao của ảnh gốc cho chiều cao bạn muốn thay đổi kích thước ảnh. Điều này sẽ duy trì tỷ lệ khung hình. Cuối cùng, xuất hình ảnh đã thay đổi kích thước.
original_img = cv2.imread('sample.jpg')
copy = original_img.copy()
ratio = original_img.shape[0] / 500.0
img_resize = imutils.resize(original_img, height=500)
cv2.imshow('Resized image', img_resize)
cv2.waitKey(0)
Đầu ra của đoạn mã trên như sau:
Bây giờ bạn đã thay đổi kích thước chiều cao của ảnh gốc thành 500 pixel.
Chuyển đổi hình ảnh đã thay đổi kích thước thành thang độ xám
Chuyển đổi hình ảnh RGB đã thay đổi kích thước thành thang độ xám. Hầu hết các thư viện xử lý ảnh chỉ hoạt động với ảnh thang độ xám vì chúng dễ xử lý hơn.
gray_image = cv2.cvtColor(img_resize, cv2.COLOR_BGR2GRAY)
cv2.imshow('Grayed Image', gray_image)
cv2.waitKey(0)
Lưu ý sự khác biệt giữa hình ảnh gốc và hình ảnh có màu xám.
Bảng màu đã chuyển sang màu đen và trắng.
Áp dụng máy dò cạnh
Áp dụng bộ lọc làm mờ Gaussian trên hình ảnh màu xám để loại bỏ nhiễu. Sau đó gọi hàm canny của OpenCV để phát hiện các cạnh có trong ảnh.
blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)
edged_img = cv2.Canny(blurred_image, 75, 200)
cv2.imshow('Image edges', edged_img)
cv2.waitKey(0)
Các cạnh có thể nhìn thấy trên đầu ra.
Các cạnh bạn sẽ làm việc với các cạnh của tài liệu.
Tìm đường bao lớn nhất
Phát hiện các đường viền có trong hình ảnh được viền. Sắp xếp chúng theo thứ tự giảm dần chỉ giữ lại năm đường viền lớn nhất. Xấp xỉ đường bao lớn nhất có bốn cạnh bằng cách lặp qua các đường bao đã sắp xếp.
cnts, _ = cv2.findContours(edged_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
if len(approx) == 4:
doc = approx
break
Đường viền với bốn cạnh có khả năng chứa tài liệu.
Khoanh tròn bốn góc của đường viền tài liệu
Khoanh tròn các góc của đường viền tài liệu được phát hiện. Điều này sẽ giúp bạn xác định xem chương trình của bạn có thể phát hiện tài liệu trong ảnh hay không.
p = []for d in doc:
tuple_point = tuple(d[0])
cv2.circle(img_resize, tuple_point, 3, (0, 0, 255), 4)
p.append(tuple_point)
cv2.imshow('Circled corner points', img_resize)
cv2.waitKey(0)
Thực hiện khoanh tròn trên hình ảnh RGB đã thay đổi kích thước.
Sau khi phát hiện tài liệu, bây giờ bạn cần trích xuất tài liệu từ hình ảnh.
Sử dụng phối cảnh dọc để có được hình ảnh mong muốn
Phối cảnh dọc là một kỹ thuật thị giác máy tính để chuyển đổi hình ảnh để sửa các biến dạng. Nó biến hình ảnh thành một mặt phẳng khác cho phép bạn xem hình ảnh từ một góc độ khác.
warped_image = perspective_transform(copy, doc.reshape(4, 2) * ratio)
warped_image = cv2.cvtColor(warped_image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Warped Image", imutils.resize(warped_image, height=650))
cv2.waitKey(0)
Để có được hình ảnh cong vênh, bạn cần tạo một mô-đun đơn giản sẽ thực hiện chuyển đổi phối cảnh.
Mô-đun chuyển đổi
Mô-đun sẽ sắp xếp thứ tự các điểm của các góc tài liệu. Nó cũng sẽ biến hình ảnh tài liệu thành một mặt phẳng khác và thay đổi góc máy ảnh thành ảnh chụp từ trên cao.
Mở tệp transform.py bạn đã tạo trước đó. Nhập thư viện OpenCV và NumPy.
import numpy as np
import cv2
Mô-đun này sẽ chứa hai chức năng. Tạo một chức năng sẽ sắp xếp tọa độ của các điểm góc tài liệu. Tọa độ đầu tiên sẽ là góc trên cùng bên trái, tọa độ thứ hai sẽ là góc trên cùng bên phải, tọa độ thứ ba sẽ là góc dưới cùng bên phải và tọa độ thứ tư sẽ là góc dưới cùng bên trái.
def order_points(pts):
rect = np.zeros((4, 2), dtype = "float32") s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
'''computing the difference between the points, the
top-right point will have the smallest difference,
whereas the bottom-left will have the largest difference'''
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
Tạo một chức năng thứ hai sẽ tính toán tọa độ góc của hình ảnh mới và chụp ảnh trên cao. Sau đó, nó sẽ tính toán ma trận biến đổi phối cảnh và trả về hình ảnh bị biến dạng.
def perspective_transform(image, pts):
rect = order_points(pts)
(tl, tr, br, bl) = rect '''compute the width of the new image, which will be the
maximum distance between bottom-right and bottom-left
x-coordinates or the top-right and top-left x-coordinates'''
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxWidth = max(int(widthA), int(widthB))
'''compute the height of the new image, which will be the
maximum distance between the top-left and bottom-left y-coordinates'''
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max(int(heightA), int(heightB))
'''construct the set of destination points to obtain an overhead shot'''
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype = "float32")
transform_matrix = cv2.getPerspectiveTransform(rect, dst)
warped = cv2.warpPerspective(image, transform_matrix, (maxWidth, maxHeight))
return warped
Bây giờ bạn đã tạo mô-đun chuyển đổi. Lỗi khi nhập Perspective_transform giờ đây sẽ biến mất.
Lưu ý rằng hình ảnh hiển thị có ảnh chụp từ trên cao.
Áp dụng ngưỡng thích ứng và lưu kết quả đã quét
Trong tệp main.py, áp dụng ngưỡng Gaussian cho hình ảnh bị biến dạng. Điều này sẽ cung cấp cho hình ảnh bị cong vênh một cái nhìn được quét. Lưu đầu ra hình ảnh đã quét vào thư mục chứa các tệp chương trình.
T = threshold_local(warped_image, 11, offset=10, method="gaussian")
warped = (warped_image > T).astype("uint8") * 255
cv2.imwrite('./'+'scan'+'.png',warped)
Lưu bản quét ở định dạng PNG sẽ duy trì chất lượng tài liệu.
Hiển thị đầu ra
Xuất hình ảnh của tài liệu được quét:
cv2.imshow("Final Scanned image", imutils.resize(warped, height=650))
cv2.waitKey(0)
cv2.destroyAllWindows()
Hình ảnh sau đây cho thấy đầu ra của chương trình, ảnh chụp từ trên cao của tài liệu được quét.
Làm thế nào để thăng tiến trong thị giác máy tính
Tạo một máy quét tài liệu bao gồm một số lĩnh vực cốt lõi của thị giác máy tính, đây là một lĩnh vực rộng lớn và phức tạp. Để thăng tiến trong thị giác máy tính, bạn nên làm việc trong các dự án thú vị nhưng đầy thử thách.
Bạn cũng nên đọc thêm về cách bạn có thể sử dụng thị giác máy tính với các công nghệ hiện tại. Điều này sẽ giúp bạn cập nhật thông tin và cung cấp cho bạn những ý tưởng mới để thực hiện các dự án.