Thị giác máy tính với OpenCV-Python Bài 4, Phần 2: Biến đổi hình ảnh
11:15 - 16/12/2021
Trong bài này chúng ta sẽ học cách áp dụng các phép biến đổi hình học khác nhau trên hình ảnh như phép tịnh tiến, phép quay, phép biến đổi affine, ...
Thị giác máy tính với OpenCV-Python Bài 7 Phần 2: Phát hiện người đi bộ trong video
Thị giác máy tính với OpenCV-Python Bài 7 Phần 1: Phát hiện người đi bộ trong hình ảnh
Thị giác máy tính với OpenCV-Python Bài 6 Phần 2: Phép trừ nền
Thị giác máy tính với OpenCV-Python Bài 6 Phần 1: Bắt bám đối tượng với Meanshift và Camshift
Các phép biến đổi
OpenCV cung cấp hai hàm biến đổi gồm cv2.warpAffine và cv2.warpPerspective, cho phép thực hiện hầu như tất cả các loại biến đổi. Hàm cv2.warpAffine lấy ma trận chuyển đổi 2x3 trong khi hàm cv2.warpPerspective lấy ma trận biến đổi 3x3 làm đầu vào.
Thay đổi kích thước hình ảnh
OpenCV hỗ trợ tăng giảm kích thước hình ảnh thông qua hàm cv2.resize(). Kích thước của hình ảnh có thể được chỉ định theo cách thủ công hoặc có thể chỉ định hệ số tỷ lệ. Các phương pháp nội suy khác nhau được sử dụng, trong đó phổ biến hơn cả là cv2.INTER_AREA để thu nhỏ, cv2.INTER_CUBIC (chậm) và cv2.INTER_LINEAR để thu phóng (zoom). Theo mặc định, phương thức nội suy được sử dụng là cv2.INTER_LINEAR cho tất cả các mục đích thay đổi kích thước ảnh. Bạn có thể thay đổi kích thước hình ảnh đầu vào theo một trong các phương thức sau:
- import cv2
- import numpy as np
- img = cv2.imread('messi.jpg')
- res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
- #OR
- height, width = img.shape[:2]
- res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
Phép dịch chuyển
Phép dịch chuyển là thao tác dịch chuyển vị trí của đối tượng. Nếu muốn dịch chuyển tịnh tiến khoảng (tx, ty) theo hướng (x, y), có thể tạo ma trận dịch chuyển M như sau:
M = [ 1 0 tx
0 1 ty ]
Chúng ta có thể đưa nó vào thành một mảng Numpy kiểu np.float32 và truyền nó vào hàm cv2.warpAffine(). Xem ví dụ dưới đây để thấy sự dịch chuyển theo (100, 50):
- import cv2
- import numpy as np
- img = cv2.imread('lampard.jpg', 0)
- rows,cols = img.shape
- M = np.float32([[1, 0, 100], [0, 1, 50]])
- dst = cv2.warpAffine(img,M,(cols, rows))
- cv2.imshow('Anh dich chuyen', dst)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
Kết quả nhận được:
Ghi chú:
Đối số thứ ba của hàm cv2.warpAffine() là kích thước của hình ảnh đầu ra, phải ở dạng **(width, height)**. Lưu ý rằng chiều rộng = số cột và chiều cao = số hàng.
Phép xoay ảnh
Xoay ảnh theo một góc θ đạt được bằng ma trận biến đổi có dạng:
M = [ cos θ -sin θ
sin θ cos θ ]
OpenCV khá linh hoạt khi cung cấp khả năng xoay theo tỷ lệ với tâm xoay có thể điều chỉnh được để xoay ở bất kỳ vị trí nào mong muốn, sử dụng hàm cv2.getRotationMatrix2D. Xem ví dụ xoay hình ảnh 90 độ so với tâm mà không thay đổi tỷ lệ hình ảnh dưới đây:
- img = cv2.imread('lampard.jpg', 0)
- rows,cols = img.shape
- M = cv2.getRotationMatrix2D((cols/2, rows/2), 90, 1)
- dst = cv2.warpAffine(img, M, (cols, rows))
Dịch chuyển Affine
Trong phép dịch chuyển affine, tất cả các đường thẳng song song trong ảnh gốc vẫn sẽ song song trong ảnh đầu ra. Để tìm ma trận biến đổi, chúng ta cần ba điểm từ ảnh đầu vào và các vị trí tương ứng của chúng trong ảnh đầu ra. Sau đó, cv2.getAffineTransform sẽ tạo một ma trận 2x3 truyền vào cv2.warpAffine.
Xem ví dụ dưới đây để rõ hơn:
- from matplotlib import pyplot as plt
- img = cv2.imread('cotuong.png')
- rows,cols,ch = img.shape
- pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
- pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
- M = cv2.getAffineTransform(pts1, pts2)
- dst = cv2.warpAffine(img, M, (cols, rows))
- plt.subplot(121), plt.imshow(img), plt.title('Input')
- plt.subplot(122), plt.imshow(dst), plt.title('Output')
- plt.show()
Biến đổi Perspective
Trong biến đổi perspective (phối cảnh), chúng ta cần một ma trận chuyển đổi 3x3. Các đường thẳng sẽ vẫn thẳng ngay cả sau khi biến đổi. Để tìm ma trận biến đổi này, cần biết 4 điểm trên ảnh đầu vào và các điểm tương ứng trên ảnh đầu ra. Trong số 4 điểm này, có 3 điểm không được thẳng hàng. Ma trận chuyển đổi có thể tìm được thông hàm cv2.getPerspectiveTransform. Sau đó, áp dụng hàm cv2.warpPerspective với ma trận biến đổi 3x3 vừa tìm được.
Xem đoạn code minh họa bên dưới:
- img = cv2.imread('cotuong2.jpg')
- rows,cols,ch = img.shape
- pts1 = np.float32([[80, 80], [492, 75], [12, 520], [598, 510]])
- pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
- M = cv2.getPerspectiveTransform(pts1, pts2)
- dst = cv2.warpPerspective(img, M, (300, 300))
- plt.subplot(121), plt.imshow(img), plt.title('Input')
- plt.subplot(122), plt.imshow(dst), plt.title('Output')
- plt.show()
Kết quả nhận được:
Ở phần tiếp theo chúng ta sẽ tìm hiểu về image thresholding (ngưỡng ảnh) để lọc bỏ nhiễu và chọn ra vùng ảnh mong muốn.
(Sưu tầm)
VIỆN IMC
Tòa nhà IMC Tower, Số 176 Trường Chinh, Phường Khương
Thượng, Quận Đống Đa, Thành phố Hà Nội, Việt Nam
Tel/Fax : (+84) 24 3566 6232 / 24 3566 6234
Email: contact@imc.org.vn Website: https://imc.org.vn