Phần 6. Xoay và dịch ảnh sử dụng OpenCV

0
6388
rotate

Bài viết này sẽ giới thiệu kỹ thuật xoay ảnh và dịch ảnh bằng OpenCV. Xoay và dịch hình ảnh là một trong những thao tác cơ bản nhất trong chỉnh sửa hình ảnh và thuộc phép biến đổi Affine – là phép biến đổi hình học bảo toàn các đường thẳng và song song (nhưng không nhất thiết là khoảng cách và góc). Hình ảnh bên dưới sẽ được sử dụng ở tất cả các ví dụ trong bài viết.

Bài viết gồm những nội dung chính sau:

1. Xoay ảnh sử dụng OpenCV

2. Dịch ảnh sử dụng OpenCV

Trước tiên quan sát đoạn code mẫu bên dưới được sử dụng để thực hiện xoay hình ảnh bằng OpenCV.

Python

import cv2

# Reading the image
image = cv2.imread('image.jpg')

# dividing height and width by 2 to get the center of the image
height, width = image.shape[:2]
# get the center coordinates of the image to create the 2D rotation matrix
center = (width/2, height/2)

# using cv2.getRotationMatrix2D() to get the rotation matrix
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

# rotate the image using cv2.warpAffine
rotated_image = cv2.warpAffine(src=image, M=rotate_matrix, dsize=(width, height))

cv2.imshow('Original image', image)
cv2.imshow('Rotated image', rotated_image)
# wait indefinitely, press any key on keyboard to exit
cv2.waitKey(0)
# save the rotated image to disk
cv2.imwrite('rotated_image.jpg', rotated_image)

C++

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;

int main(int, char**) 
{
    Mat image = imread("image.jpg");
	  imshow("image", image);
	  waitKey(0);
	  double angle = 45;

	  // get the center coordinates of the image to create the 2D rotation matrix
	  Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0);
	  // using getRotationMatrix2D() to get the rotation matrix
	  Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);

	  // we will save the resulting image in rotated_image matrix
	  Mat rotated_image;
	  // rotate the image using warpAffine
	  warpAffine(image, rotated_image, rotation_matix, image.size());
	  imshow("Rotated image", rotated_image);
    // wait indefinitely, press any key on keyboard to exit
	  waitKey(0);
	  // save the rotated image to disk
	  imwrite("rotated_im.jpg", rotated_image);

	  return 0;
}

1. Xoay ảnh sử dụng OpenCV

Bạn có thể xoay một ảnh với một góc θ bằng cách xác định ma trận chuyển đổi M có dạng như sau:

OpenCV cho phép xác định tâm quay cho hình ảnh và hệ số tỷ lệ để thay đổi kích thước hình ảnh. Trong trường hợp đó, ma trận chuyển đổi có dạng sau:

Trong đó cx & cy là tọa độ mà hình ảnh được xoay.

OpenCV cung cấp hàm getRotationMatrix2D() để tạo ra ma trận chuyển đổi ở trên. Cú pháp như sau:

getRotationMatrix2D(center, angle, scale)

Hàm getRotationMatrix2D() gồm các đối số sau:

center: tâm xoay của hình ảnh

– angle: góc quay theo độ

scale: hệ số tỷ lệ đẳng hướng giúp chia tỷ lệ hình ảnh lên hoặc xuống theo giá trị được khai báo.

Nếu angle dương, hình ảnh sẽ được quay theo hướng ngược chiều kim đồng hồ. Nếu muốn xoay hình ảnh theo chiều kim đồng hồ với cùng một lượng, thì angle cần phải âm.

Xoay ảnh gồm ba bước:

– Đầu tiên, cần lấy tâm của vòng quay. Đây thường là tâm của hình ảnh mà bạn đang định xoay.

– Tiếp theo, tạo ma trận quay 2D. OpenCV cung cấp hàm getRotationMatrix2D() mà đã giới thiệu ở trên.

– Cuối cùng, áp dụng phép biến đổi affine cho hình ảnh, sử dụng ma trận chuyển đổi đã tạo ở bước trước. Hàm warpAffine() trong OpenCV sẽ thực hiện công việc này.

Hàm warpAffine() áp dụng một phép biến đổi affine cho hình ảnh. Sau khi áp dụng phép biến đổi affine, tất cả các đường thẳng song song trong hình ảnh ban đầu cũng sẽ vẫn song song trong hình ảnh đầu ra.

Cú pháp cho hàm warpAffine():

warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

Hàm có các đối số sau:

src: đường dẫn ảnh đầu vào

– M: ma trận biến đổi

– dsize: kích thước của hình ảnh đầu ra

– dst: hình ảnh đầu ra

– flags: cờ kết hợp các phương pháp nội suy như INTER_LINEAR hoặc INTER_NEAREST

– borderMode: phương pháp ngoại suy pixel

borderValue: giá trị được sử dụng trong trường hợp đường viền không đổi, có giá trị mặc định là 0

* Có thể tìm hiểu thêm về các phép biến đổi affine tại đây. Bây giờ sẽ đi cụ thể vào code. Đầu tiên là khai báo thư viện OpenCV và đọc ảnh đầu vào.

Python

import cv2

# Reading the image
image = cv2.imread('image.jpg')

C++

#include "opencv2/opencv.hpp"
using namespace cv;

# Reading the image
Mat image = imread("image.jpg");

Tiếp theo, tính toán điểm tâm xoay, trong ví dụ này, sẽ là tâm của hình ảnh. Để làm điều này, chỉ cần chia chiều rộng và chiều cao của hình ảnh cho 2.

Python

# Dividing height and width by 2 to get the center of the image
height, width = image.shape[:2]
center = (width/2, height/2)

C++

// get the center coordinates of the image to create the 2D rotation matrix
Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0);

Khi đã có tọa độ pixel của tâm hình ảnh, tiếp theo sẽ tính toán ma trận chuyển đổi bằng cách sử dụng hàm getRotationMatrix2D() với các đầu vào:

– Điểm trung tâm để xoay hình ảnh

– Góc quay, tính bằng độ (giá trị dương, tương ứng với xoay ngược chiều kim đồng hồ)

– Hệ số tỷ lệ đẳng hướng để thay đổi kích thước hình ảnh. Có thể là một giá trị dấu phẩy động. Ví dụ: giá trị 1,0 sẽ giữ cho hình ảnh đầu ra có cùng kích thước với hình ảnh gốc. Giá trị 2.0 sẽ làm hình ảnh thu được có kích thước gấp đôi kích thước của hình ảnh gốc.

Kết quả mà hàm trả về là một trận chuyển đổi 2D sẽ được sử dụng ở bước tiếp theo để xoay hình ảnh.

Python

# the above center is the center of rotation axis
# use cv2.getRotationMatrix2D() to get the rotation matrix
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

C++

// create the rotation matrix using the image center
Mat rotation_matix = getRotationMatrix2D(center, angle=45, 1.0);

Tiếp theo sử dụng hàm warpAffine(). Hàm yêu cầu ba đầu vào:

– Hình ảnh gốc

– Ma trận chuyển đổi

– Kích thước của hình ảnh đầu ra

Hình ảnh được xoay sau đó được lưu trữ trong rotated_image.

Python

# Rotate the image using cv2.warpAffine
rotated_image = cv2.warpAffine(src=image, M=rotate_matrix, dsize=(width, height))

C++

// we will save the resulting image in rotated_image matrix
Mat rotated_image;
// apply affine transformation to the original image using the 2D rotation matrix
warpAffine(image, rotated_image, rotation_matix, image.size());

Sử dụng hàm imshow() để quan sát kết quả.

Python

# visualize the original and the rotated image
cv2.imshow('Original image', image)
cv2.imshow('Rotated image', rotated_image)
# wait indefinitely, press any key on keyboard to exit
cv2.waitKey(0)
# write the output, the rotated image to disk
cv2.imwrite('rotated_image.jpg', rotated_image)

C++

imshow("Rotated image", rotated_image);
waitKey(0);
// save the rotated image to disk
imwrite("rotated_im.jpg", rotated_image);

2. Dịch ảnh sử dụng OpenCV

Trong thị giác máy tính, việc dịch một hình ảnh có nghĩa là dịch chuyển nó theo một số pixel cụ thể, dọc theo các trục x và y. Đặt các pixel mà hình ảnh cần dịch chuyển là tx và ty. Xác định ma trận dịch M có dạng như sau:

Một số điểm cần lưu ý khi thay đổi hình ảnh theo các giá trị tx và ty.

– Giá trị tx dương sẽ chuyển hình ảnh sang phải và các giá trị âm sẽ chuyển hình ảnh sang trái.

– Tương tự, các giá trị dương của ty sẽ chuyển hình ảnh xuống trong khi các giá trị âm sẽ chuyển hình ảnh lên trên.

Thực hiện các bước sau để dịch hình ảnh bằng OpenCV:

– Đầu tiên, đọc hình ảnh, lấy chiều rộng và chiều cao của nó.

– Tiếp theo, giống như đã làm đối với phép xoay ảnh, tạo một ma trận chuyển đổi, là một mảng 2D. Ma trận này chứa thông tin cần thiết để dịch chuyển hình ảnh, dọc theo trục x và y.

– Sử dụng hàm warpAffine(), trong bước cuối cùng này, để áp dụng phép biến đổi affine.

Dưới đây là code tham khảo việc dịch hình ảnh:

Python

import cv2 
import numpy as np

# read the image 
image = cv2.imread('image.jpg')
# get the width and height of the image
height, width = image.shape[:2]

C++

#include "opencv2/opencv.hpp"
using namespace cv
// read the image 
Mat image = imread("image.jpg");
// get the height and width of the image
int height = image.cols;
int width = image.rows;

Tiếp theo tạo ma trận chuyển đổi:

Python

# get tx and ty values for translation
# you can specify any value of your choice
tx, ty = width / 4, height / 4

# create the translation matrix using tx and ty, it is a NumPy array 
translation_matrix = np.array([
    [1, 0, tx],
    [0, 1, ty]
], dtype=np.float32)

C++

// get tx and ty values for translation
float tx = float(width) / 4;
float ty = float(height) / 4;
// create the translation matrix using tx and ty
float warp_values[] = { 1.0, 0.0, tx, 0.0, 1.0, ty };
Mat translation_matrix = Mat(2, 3, CV_32F, warp_values);

Đối với ma trận dịch, như đã giới thiệu ở trên thì sẽ cần tx và ty. Ví dụ này đang lấy một phần tư chiều rộng và chiều cao làm giá trị dịch. Áp dụng ma trận dịch cho hình ảnh, sử dụng hàm warpAffine(), giống như cách đã làm để xoay hình ảnh.

Python

# apply the translation to the image
translated_image = cv2.warpAffine(src=image, M=translation_matrix, dsize=(width, height))

C++

// save the resulting image in translated_image matrix
Mat translated_image;
// apply affine transformation to the original image using the translation matrix
warpAffine(image, translated_image, translation_matrix, image.size());

*Lưu ý: warpAffine() là một hàm chung có thể được sử dụng để áp dụng bất kỳ kiểu chuyển đổi affine nào cho một hình ảnh. Chỉ cần xác định ma trận M một cách thích hợp.

Tiếp theo hiển thị kết quả hình ảnh đã dịch và lưu nó vào thư mục.

Python

# display the original and the Translated images
cv2.imshow('Translated image', translated_image)
cv2.imshow('Original image', image)
cv2.waitKey(0)
# save the translated image to disk
cv2.imwrite('translated_image.jpg', translated_image)

C++

//display the original and the Translated images
imshow("Translated image", translated_image);
imshow("Original image", image);
waitKey(0);
// save the translated image to disk
imwrite("translated_image.jpg", translated_image);

Kết luận:

Trong bài viết này, bạn đã được giới thiệu về các thao tác dịch và xoay ảnh bằng OpenCV. Bài viết bắt đầu với việc xoay hình ảnh bằng OpenCV trong đó sử dụng hàm getRotationMatrix2D() để thu được ma trận xoay 2D. Sau đó, chuyển ma trận xoay này cho hàm warpAffine() để xoay hình ảnh về điểm trung tâm của nó theo một góc mong muốn.

Tiếp theo là dịch hình ảnh bằng OpenCV. Đối với thao tác này, bạn cần xác định một ma trận dịch chứa các giá trị x và y mà muốn dịch hình ảnh. Để dịch, bạn cũng sử dụng hàm warpAffine() để áp dụng phép chuyển đổi.

Phép quay và dịch ảnh là một trong những phép biến đổi hình học cơ bản nhất có thể được thực hiện và sẽ cung cấp một nền tảng tốt để tìm hiểu về các phép biến đổi khác có thể được thực hiện bằng OpenCV. Bạn có thể sử dụng những ví dụ trên nhưng thay đổi đầu vào và xem kết quả để hiểu rõ hơn.

Ở bài viết tiếp theo, chúng ta sẽ cùng tìm hiểu cách ghi chú trên hình ảnh bằng OpenCV (Annotating Images).

Biên dịch: Thảo Nguyễn

Để cập nhật tin tức công nghệ mới nhất và các sản phẩm của công ty AIoT JSC, vui lòng truy cập link: http://aiots.vn hoặc linhkienaiot.com

0 0 Phiếu bầu
Article Rating
Subscribe
Notify of
guest
0 Comments
Phản hồi nội tuyến
Xem tất cả các bình luận